Home > Net >  I am not able to save retrieve data using shared preferences in Flutter
I am not able to save retrieve data using shared preferences in Flutter

Time:03-17

I am using flutter localizations for changing language in my flutter app. I want to change my app's language in real time and have implemented logic for that. Now, I want that when user closes app and restarts it, he gets same language he chose before, i.e. language should not set back to default after user closes the app. For this purpose, I was using shared preferences to save the code of language that user selected and then retrieve it in the beginning of the app.

app_locale.dart -

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

class AppLocale extends ChangeNotifier {
  Locale? _locale;

  Locale get locale => _locale ?? Locale('en');

  void getLocale() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String code = prefs.getString("code")??"en";
    Locale newLocale = Locale(code);
    if(newLocale == Locale('bn')) {
      _locale = Locale('bn');
    } else if(newLocale==Locale('gu')){
      _locale = Locale('gu');
    } else if(newLocale==Locale('en')){
      _locale = Locale('en');
    } else if(newLocale==Locale('pa')){
      _locale = Locale('pa');
    }
  }

  void changeLocale(Locale newLocale) async {
    if(newLocale == Locale('bn')) {
      _locale = Locale('bn');
    } else if(newLocale==Locale('gu')){
      _locale = Locale('gu');
    } else if(newLocale==Locale('en')){
      _locale = Locale('en');
    } else if(newLocale==Locale('pa')){
      _locale = Locale('pa');
    }
    SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.setString("code", _locale?.countryCode??"en");
    notifyListeners();
  }
}

I am calling getLocale in main.dart -

class MyApp extends StatelessWidget {
  GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey=GlobalKey<ScaffoldMessengerState>();
  Locale? defaultLanguage;
  @override
  Widget build(BuildContext context) {
    var language = Provider.of<AppLocale>(context);
    language.getLocale();
    return Consumer<AppLocale>(
    ........
    ........

And in my language selection screen, I am changing language like this -

var language = Provider.of<AppLocale>(context);

 child: Column(
                children: [
                  LanguageTile(
                    shortForm: "Pa",
                    fullName: "ਪੰਜਾਬੀ",
                    isSelected: selectedLanguage==0,
                    onTap: () {
                      changeSelectedLanguage(0);
                      language.changeLocale(Locale('pa'));
                    },
                  ),
                  LanguageTile(
                    shortForm: "GU",
                    fullName: "ગુજરાતી",
                    isSelected: selectedLanguage==1,
                    onTap: () {
                      changeSelectedLanguage(1);
                      language.changeLocale(Locale('gu'));
                    },
                  ),
                  LanguageTile(
                    shortForm: "বা",
                    fullName: "বাংলা",
                    isSelected: selectedLanguage==2,
                    onTap: () {
                      changeSelectedLanguage(2);
                      language.changeLocale(Locale('bn'));
                    },
                  ),
                  LanguageTile(
                    shortForm: "A",
                    fullName: "English",
                    isSelected: selectedLanguage==3,
                    onTap: () {
                      changeSelectedLanguage(3);
                      language.changeLocale(Locale('en'));
                    },
                  ),
                  //Text(AppLocalizations.of(context)!.helloWorld),
                ],
              ),

Please someone guide me for this.

Heading

CodePudding user response:

You have to call the get language method in initState. Or show a loading or pop up while the data is loading in background. Sometimes it happens because data is not loaded yet and build context already create the screen and the ui. I hope this will work.

CodePudding user response:

why yout dont use ListView().builder or Grid().builder to habe less code and use a list with all entries and les

child: ListView.builder(
            itemCount: list.length,
              itemBuilder: (context, i){
                return LanguageTile(
                shortForm: list[i].shortForm,
                fullName: list[i].fullName,
                 onSelected: (value) {
                  changeSelectedLanguage(value);
                  language.changeLocale(Locale('en'));
                },
              ),
                }
              },
          ),

CodePudding user response:

the data is not coming because when loading data from SharedPreferences it take time.so method is not in void it in Future. please paste the below code

Future getLocale() async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        String code = prefs.getString("code")??"en";
        Locale newLocale = Locale(code);
        if(newLocale == Locale('bn')) {
          _locale = Locale('bn');
        } else if(newLocale==Locale('gu')){
          _locale = Locale('gu');
        } else if(newLocale==Locale('en')){
          _locale = Locale('en');
        } else if(newLocale==Locale('pa')){
          _locale = Locale('pa');
        }
      }


   

     class MyApp extends StatelessWidget {
          GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey=GlobalKey<ScaffoldMessengerState>();
          Locale? defaultLanguage;
          var language;
          void initmethod(context)async
          {
             language =  await Provider.of<AppLocale>(context).getLocale();
          }
          @override
          Widget build(BuildContext context) {
           initmethod(context);
            return Consumer<AppLocale>(
            ........
            ........
  • Related