Nomad09
Nomad09

Reputation: 199

using Shared preferences with a change notifier

I'm trying to understand how to use shared preferences with a change notifier. I've created a basic app and I want to save a bool and a string from the change notifier using shared preferences. here is my main.dart:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => GlobalSettings1()),
        ChangeNotifierProvider(create: (_) => SectionSettings1()),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        initialRoute: '/seventh',
        routes: {
          '/': (context) => Page01(),
          '/first': (context) => Page02(),
          '/second': (context) => Page03(),
        });
  }
}

and here is page01

class _Page01State extends State<Page01> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          InkWell(
            onTap: () {
              context.read<GlobalSettings1>().ToggleSwitch();
            },
            child: Container(
              height: 30,
              width: 80,
              color: context.watch<GlobalSettings1>().toggleSwitch01
                  ? Colors.green
                  : Colors.red,
            ),
          ),
          SizedBox(
            height: 20,
          ),
          InkWell(
              onTap: () {
                showDialog(
                  context: context,
                  builder: (BuildContext context) => Material(
                    color: Colors.transparent,
                    child: Buttons(
                      onTap: (val) {
                        context.read<GlobalSettings1>().StringToSave(val);
                        Navigator.pop(context);
                      },
                    ),
                  ),
                );
              },
              child: Container(
                height: 30,
                width: 80,
                child: Center(
                  child: Text(
                    context.watch()<GlobalSettings1>().stringToSave,
                  ),
                ),
              )),
        ],
      ),
    );
  }
}

and finally, here is my change notifier:

class Buttons extends StatelessWidget {
  const Buttons({Key? key, required this.onTap}) : super(key: key);
  final ValueChanged? onTap;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        InkWell(
            onTap: () {
              if (onTap != null) {
                onTap!('Choice01');
              }
            },
            child: Container(
              height: 30,
              width: 80,
              child: Text('Choice01'),
            )),
        SizedBox(
          height: 30,
        ),
        InkWell(
            onTap: () {
              if (onTap != null) {
                onTap!('Choice02');
              }
            },
            child: Container(
              height: 30,
              width: 80,
              child: Text('Choice02'),
            )),
      ],
    );
  }
}

class GlobalSettings1 with ChangeNotifier {
  bool _toggleSwitch01 = true;
  String _stringToSave = 'Choice01';

  final SharedPreferences prefs;

  GlobalSettings1({required this.prefs});

  bool get toggleSwitch01 => _toggleSwitch01;
  String get stringToSave => _stringToSave;

  void ToggleSwitch() {
    _toggleSwitch01 = !_toggleSwitch01;
    _setPrefItems();
    notifyListeners();
  }

  void StringToSave(val) {
    _stringToSave = val;
    _setPrefItems();
    notifyListeners();
  }

  void _setPrefItems() {
    prefs.setBool('toggleSwitch01', _toggleSwitch01);
    prefs.setString('stringToSave', _stringToSave);
    notifyListeners();
  }

  void _getPrefItems() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    _stringToSave = prefs.getString('stringToSave') ?? '';
    _toggleSwitch01 = prefs.getBool('autoUpdateVariables') ?? true;
    notifyListeners();
  }

  bool getToggleSwitch01() {
    _getPrefItems();
    return _toggleSwitch01;
  }

  String getStringToSave() {
    _getPrefItems();
    return _stringToSave;
  }
}

As you can see, there is a bool that is toggled in Page01 and a String that is displayed from a value that is generated and passed through from the buttons widget.

After looking at other tutorials on this matter, I think i have the change notifier set up correctly but am unsure about how to set up the main.dart and Page01 so that when the bool and String are set, they stay like that when the app is rebooted.

i'm currently getting an error in main.dart:

ChangeNotifierProvider(create: (_) => GlobalSettings1()),

asking me to add required argument prefs but i'm unsure what the code should be to go in the brackets.

thanks so much and any help would be greatly appreciated.

Upvotes: 1

Views: 1092

Answers (2)

Md. Yeasin Sheikh
Md. Yeasin Sheikh

Reputation: 63549

Currently, you are passing an instance on constructor.

 GlobalSettings1({required this.prefs});

While it is SharedPreferences you can do get instance with

class GlobalSettings1 with ChangeNotifier {
  bool _toggleSwitch01 = true;
  String _stringToSave = 'Choice01';

  GlobalSettings1();

  ......

  void _setPrefItems() async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setBool('toggleSwitch01', _toggleSwitch01);
    prefs.setString('stringToSave', _stringToSave);
    notifyListeners();
  }

Upvotes: 0

eamirho3ein
eamirho3ein

Reputation: 17880

You need pass an instance of SharedPreferences to your GlobalSettings1, also change GlobalSettings1 to this:

class GlobalSettings1 with ChangeNotifier {
  bool _toggleSwitch01 = true;
  String _stringToSave = 'Choice01';

  final SharedPreferences prefs;

  GlobalSettings1({required this.prefs});

  bool get toggleSwitch01 => _toggleSwitch01;
  String get stringToSave => _stringToSave;

  void ToggleSwitch() {
    _toggleSwitch01 = !_toggleSwitch01;
    _setPrefItems();
    notifyListeners();
  }

  void StringToSave(val) {
    _stringToSave = val;
    _setPrefItems();
    notifyListeners();
  }

  void _setPrefItems() {
    prefs.setBool('toggleSwitch01', _toggleSwitch01);
    prefs.setString('stringToSave', _stringToSave);
    notifyListeners();
  }

  void _getPrefItems() { // <=== change this
    _stringToSave = prefs.getString('stringToSave') ?? '';
    _toggleSwitch01 = prefs.getBool('autoUpdateVariables') ?? true;
    notifyListeners();
  }

  bool getToggleSwitch01() {
    _getPrefItems();
    return _toggleSwitch01;
  }

  String getStringToSave() {
    _getPrefItems();
    return _stringToSave;
  }
}

then change your main to this:

void main() {   
    SharedPreferences prefs = await SharedPreferences.getInstance();
    runApp(
        MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (_) => GlobalSettings1(prefs: prefs)),
            ChangeNotifierProvider(create: (_) => SectionSettings1()),
          ],
          child: MyApp(),
        ),
    );
}

Upvotes: 1

Related Questions