Floris Marpepa
Floris Marpepa

Reputation: 2081

flutter sharedpreferences not setting state from first built

I am trying to have values saved in sharedPreferences loaded when the app loads. But it gives me always the static list of double declared [0,0,0,0,0,0] at first built. whenever i touch something that set the state it changes to my correct values. I don't even need that static list I am just declaring it because dart is asking me. I want the default list if there is nothing already saved in there, otherwise I want the sharedpreferences saved list. here is my code.

@override initState()  {
    super.initState();
    callLoad();
  }

  callLoad() async{
    List<double> list = await loadTimers();
    setState((){
      timersList = list;
    });
  }

  Future<List<double>> loadTimers() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    List<String> myList =  prefs.getStringList('TimerList');
    List<double> defaultTimersList = [30.0, 60.0, 90.0, 120.0, 150.0, 180.0];
    List<double> savedTimerList;
      if (myList == null ){
        return defaultTimersList;
      } else{
        savedTimerList = myList.map((i)=> double.parse(i)).toList();
        return savedTimerList;
      }
  }

  static List<double> timersList = [0,0,0,0,0,0];

  double timeRemaining1 = timersList[0];
  double timeRemaining2 = timersList[1];
  double timeRemaining3 = timersList[2];
  double timeRemaining4 = timersList[3];
  double timeRemaining5 = timersList[4];
  double timeRemaining6 = timersList[5];

I tried this way too but it is the same.

@override initState()  {
    super.initState();
    loadTimers();
  }


  loadTimers() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    List<String> myList =  prefs.getStringList('TimerList');
    List<double> defaultTimersList = [30.0, 60.0, 90.0, 120.0, 150.0, 180.0];
    List<double> savedTimerList;
      if (myList == null ){
        setState(() {
          timersList = defaultTimersList;

        });
      } else{
        savedTimerList = myList.map((i)=> double.parse(i)).toList();
         setState(() {
           timersList = savedTimerList;
         });
      }
  }

  static List<double> timersList = [0,0,0,0,0,0];

  double timeRemaining1 = timersList[0];
  double timeRemaining2 = timersList[1];
  double timeRemaining3 = timersList[2];
  double timeRemaining4 = timersList[3];
  double timeRemaining5 = timersList[4];
  double timeRemaining6 = timersList[5];

Thank you

Edit with little app showing the problem.

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo chokuns page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  @override initState()  {
    super.initState();
    callLoad();
  }

  callLoad() async{
    List<double> list = await loadTimers();
    setState((){
      timersList = list;
    });
  }

  Future<List<double>> loadTimers() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    List<String> myList =  prefs.getStringList('TimerList');
    List<double> defaultTimersList = [30.0, 60.0, 90.0, 120.0, 150.0, 180.0];
    List<double> savedTimerList;
    if (myList == null ){
      return defaultTimersList;
    } else{
      savedTimerList = myList.map((i)=> double.parse(i)).toList();
      return savedTimerList;
    }
  }

  static List<double> timersList = [0,0,0,0,0,0];

  double timeRemaining1 = timersList[0];
  double timeRemaining2 = timersList[1];
  double timeRemaining3 = timersList[2];
  double timeRemaining4 = timersList[3];
  double timeRemaining5 = timersList[4];
  double timeRemaining6 = timersList[5];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button \nthis many times:',
              textAlign: TextAlign.center,
            ),
            Text(
              '$timeRemaining1', //showing here $timersList it shows correct values
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
    );
  }
}

Upvotes: 0

Views: 1373

Answers (2)

yaho cho
yaho cho

Reputation: 1779

Basically, Dart is passing by reference of object. So, Your idea is correct. But, I will explain why it does not work. It is caused by List<double> list = await loadTimers(); because it is new object. Below code shows TrueTrue. But, If you change //isSameList = identical(timersList, timersList2); to isSameList = identical(timersList, timersList2);, It shows FalseTrue. You have to restart it.

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  SharedPreferences prefs;
  static List<double> timersList = [0,0,0,0,0,0];
  double timeRemaining1;
  List<double> timersList2;
  bool isSameList;
  bool isSameValue;

  @override initState()  {
    super.initState();
    initValues();
    callLoad();
  }

  void initValues()
  {
    timeRemaining1 = timersList[0];
    timersList2 = timersList;
    isSameList = identical(timersList, timersList2);
    isSameValue = identical(timersList[0], timeRemaining1);
  }

  Future<void> callLoad() async{
    prefs = await SharedPreferences.getInstance();
    List<double> list = await loadTimers();
    setState((){
      timersList = list;
      //isSameList = identical(timersList, timersList2);
    });
  }

  List<double> loadTimers() {
    List<String> myList =  prefs.getStringList('TimerList');
    List<double> defaultTimersList = [30.0, 60.0, 90.0, 120.0, 150.0, 180.0];
    List<double> savedTimerList;
    if (myList == null ){
      return defaultTimersList;
    } else{
      savedTimerList = myList.map((i)=> double.parse(i)).toList();
      return savedTimerList;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button \nthis many times:',
              textAlign: TextAlign.center,
            ),
            Text(
              '$isSameList'+'$isSameValue', //showing here $timersList it shows correct values
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
    );
  }

Finally, I could know how to use pass by reference for the list.

timersList.setAll(0, list);

It shows the result well. But, timeRemaining1 still can not be showed becuase it can not keep the reference. So, I think you can handle it with List object as above way.

Upvotes: 0

Richard Heap
Richard Heap

Reputation: 51682

Change callLoad to:

  callLoad() async{
    List<double> list = await loadTimers();
    setState((){
      timersList = list;
      timeRemaining1 = timersList[0];
      timeRemaining2 = timersList[1];
      timeRemaining3 = timersList[2];
      timeRemaining4 = timersList[3];
      timeRemaining5 = timersList[4];
      timeRemaining6 = timersList[5];
    });
  }

Upvotes: 1

Related Questions