flutterdartflutter-dependenciesflutter-sharedpreference

Widget Not Updating Information from shared_preferences in Flutter


I was making a settings page for my flutter app to save a single number. I used shared_preferences. It can save the value into saved_preferences, and it can retrieve the data, but when settings page is loaded again it doesn't load the data into the widget. Here are some pictures to show what is happening.

Here is when I first enter the settings page, the max value in dart is set to null and the key in the shared_preferences doesn't exist.

Here is after I input a value, the max value in dart is 7574 and a key called max with the value 7574.

Here is after I exit the page and come back. The max value in dart is null but the shared_preferences data is still 7574.

I believe it has something to do with the async, because the widgets are already loading without it first getting the data from shared_preferences. But I don't know why the setState() wouldn't handle that after the data has loaded.

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

class Settings extends StatefulWidget {
  const Settings({Key? key}) : super(key: key);

  @override
  State<Settings> createState() => _SettingsState();
}

class _SettingsState extends State<Settings> {
  late SharedPreferences preferences;
  int? max;

  _loadMax() async {
    preferences = await SharedPreferences.getInstance();
    if (!preferences.containsKey('max')) {
      _setMax(16);
    } else {
      max = preferences.getInt('max');
      setState(() {});
    }
  }

  _setMax(int value) async {
    await preferences.setInt('max', value);
    max = value;
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    if (max == null) _loadMax();
    return Scaffold(
      body: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'Max Number (Inclusive) ',
                  style: Theme.of(context).textTheme.titleMedium,
                ),
                const SizedBox(width: 10.0),
                SizedBox(
                  width: 100,
                  height: 50,
                  child: TextFormField(
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                      labelText: 'Maximum',
                      counterText: '',
                    ),
                    initialValue: max.toString(),
                    inputFormatters: [
                      FilteringTextInputFormatter.allow(RegExp(r"[0-9.]")),
                    ],
                    onFieldSubmitted: (s) {
                      _setMax(int.parse(s));
                    },
                    maxLength: 4,
                    keyboardType: TextInputType.number,
                  ),
                ),
              ],
            ),
            ElevatedButton(
              onPressed: () => Navigator.pop(context),
              child: const Text('Home'),
            ),
          ]),
    );
  }
}


Solution

  • import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    
    class Settings extends StatefulWidget {
      const Settings({Key? key}) : super(key: key);
    
      @override
      State<Settings> createState() => _SettingsState();
    }
    
    class _SettingsState extends State<Settings> {
      late SharedPreferences preferences;
      int? max;
      TextEditingController textFeildData = TextEditingController();
    
      _loadMax() async {
        preferences = await SharedPreferences.getInstance();
        if (!preferences.containsKey('max')) {
          _setMax(16);
        } else {
          textFeildData.text = preferences.getInt('max').toString();
          print(textFeildData);
          setState(() {});
        }
      }
    
      _setMax(int value) async {
        await preferences.setInt('max', value);
        max = value;
        setState(() {});
      }
    
      @override
      Widget build(BuildContext context) {
        // if (max == null) _loadMax();
        return Scaffold(
          body: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'Max Number (Inclusive) ',
                  style: Theme.of(context).textTheme.titleMedium,
                ),
                const SizedBox(width: 10.0),
                SizedBox(
                  width: 100,
                  height: 50,
                  child: TextFormField(
                    controller: textFeildData,
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                      // labelText: 'Maximum',
                    ),
                    // initialValue: max.toString(),
                    inputFormatters: [
                      FilteringTextInputFormatter.allow(RegExp(r"[0-9.]")),
                    ],
                    onFieldSubmitted: (s) {
                      _setMax(int.parse(s));
                    },
                    maxLength: 4,
                    keyboardType: TextInputType.number,
                  ),
                ),
              ],
            ),
            ElevatedButton(
              onPressed: () => Navigator.pop(context),
              child: const Text('Home'),
            ),
          ]),
        );
      }
    }
    

    hopefully this will help just give textfield a controller and do what ever you want with the field text