Ad

Flutter: MVVM Architecture With Shared Preferences & Provider

I am trying to build a reusable function of Shared Preference & provider using MVVM architecture. However, I not sure how to initialize the ChangeNotifierProvider at my main. dart file. Below is the code I have.

class LanguagePreference {
  SharedPreferences prefs;

  LanguagePreference({required this.prefs});

  
  addUserLanguage(String lang) async {
    await SharedPreferences.getInstance();
    prefs.setString('userLanguage', "$lang");
  }

  
  getUserLanguage() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    //Return String
    return prefs.getString('userLanguage');
  }

}
  class LanguagePreferenceVM extends ChangeNotifier {
  LanguagePreference languagepreference;

  LanguagePreferenceVM({required this.languagePreference});

  String userLanguage = '';

  addUserLanguage(String newUserLanguage) async {
    await languagePreference.addUserLanguage(newUserLanguage);
  }

  getUserLanguage() async {
    userLanguage = await languagePreference.getUserLanguage();
    notifyListeners();
  }

  
}
 class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [],
      child: MaterialApp(
      ),
    );
  }
}

Ad

Answer

Here is a comprehensive example, below. Notes:

  • There is no need to pass SharedPreferences to your model as it has a static method to get the instance.
  • I use Provider.of<LanguagePreferenceVM> to get the provider to update the language.
  • I use Consumer<LanguagePreferenceVM> to get the provider to display the language when it notifies listeners.
  • I use FutureBuilder to handle the async result.

Example code:

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

class LanguagePreference {
  SharedPreferences _prefs;

  Future<void> getSharedPreferences() async {
    if (_prefs == null) {
      _prefs = await SharedPreferences.getInstance();
    }
  }

  LanguagePreference();

  Future<void> addUserLanguage(String lang) async {
    await getSharedPreferences();
    _prefs.setString('userLanguage', "$lang");
  }

  Future<String> getUserLanguage() async {
    //Return String
    try {
      await getSharedPreferences();
      var language = _prefs.getString('userLanguage');
      return language;
    } catch (e) {
      return '';
    }
  }
}

class LanguagePreferenceVM extends ChangeNotifier {
  LanguagePreference languagePreference;

  LanguagePreferenceVM({@required this.languagePreference});

  String userLanguage = '';

  Future<void> setUserLanguage(String newUserLanguage) async {
    await languagePreference.addUserLanguage(newUserLanguage);
    userLanguage = newUserLanguage;
  }

  Future<String> getUserLanguage() async {
    userLanguage = await languagePreference.getUserLanguage();
    return userLanguage;
  }
}

class PrefsTest extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<LanguagePreferenceVM>(
          create: (ctx) =>
              LanguagePreferenceVM(languagePreference: LanguagePreference()),
        ),
      ],
      child: PrefsTest2(),
    );
  }
}

class PrefsTest2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var languagePreferenceVM =
        Provider.of<LanguagePreferenceVM>(context, listen: false);
    languagePreferenceVM.setUserLanguage('English');
    return Scaffold(
      appBar: AppBar(title: Text('Prefs')),
      body: Consumer<LanguagePreferenceVM>(
        builder: (ctx, languagePreferenceVM, child) => FutureBuilder(
          future: languagePreferenceVM.getUserLanguage(),
          builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
            switch (snapshot.connectionState) {
              case ConnectionState.waiting:
                return const CircularProgressIndicator();
              default:
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                } else {
                  return Text('User language: ${snapshot.data}');
                }
            }
          },
        ),
      ),
    );
  }
}
Ad
source: stackoverflow.com
Ad