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(
),
);
}
}
Here is a comprehensive example, below. Notes:
SharedPreferences
to your model as it has a static method to get the instance.Provider.of<LanguagePreferenceVM>
to get the provider to update the language.Consumer<LanguagePreferenceVM>
to get the provider to display the language when it notifies listeners.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}');
}
}
},
),
),
);
}
}