Search code examples
fluttermobilesharedpreferencesflutter-futurebuilder

how to update the FutureBuilder text every time the shared-preference is updated


I wanted to keep the time data stored in the mobile localcaly so when ever the app is closed and open backed i want it to be shown. that part works but when ever the button is pressed to set new time it wont update to the newly set sharedprefence to show instead of the load or the new time.

This is the function that runs every time the button is being pressed

void timeInPush()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
String now =await new DateFormat.yMd().add_Hm().format(new DateTime.now());
String day =await new DateFormat.d().add_Hm().format(new DateTime.now());
sharedPreferences.setString("timeIn", now);
sharedPreferences.setString("timeOut",null);
sharedPreferences.reload();
}

This is the function for the Future builder

  Future <String> timeShowtimein()async{
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return Future.delayed(Duration(seconds: 1),()async{
  return await sharedPreferences.getString("timeIn");
});

}

And here is the UI builder

  Container  timeText(){
return Container(
    child:Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        FutureBuilder(
            future:timeShowtimein() ,
            builder: (context, snapshot){
              if(snapshot.hasData){
                return Text("${snapshot.data}");
              }else{
                return Text("Loading");
              }
            }),
        SizedBox(
          width:20,
        ),
        Text("$Timeout",style:TextStyle(
            color: Colors.redAccent,
            fontSize: 15.0))
      ],
    )
);
}

Solution

  • Calling timeInPush() sets the values in the Shared Preferences. The problem is that it does not let the FutureBuilder know that changes have occurred.

    sharedPreferences.reload() re-syncs the preferences with the native application to make sure that there are no pending changes in the dart side of things (It is stated in the documentation)

    Try converting your widget to stateful and call setState(() { }) in the timeInPush() method after setting the values. This might force a rebuild and fire up the future builder again.

    The problem is that it might show loading for a frame or two every time the widget rebuilds. You can fix this using initialData property = an additional variable that you might need to update manually every time you set the values in shared prefs but that will just make the code more complex. Moreover, every time you update the sharedPrefs, you will need to call setState to force the rebuild.

    I will recommend rx_shared_preferences package. It's built on top of shared_preferences package and has the ability to work with streams. With StreamBuilder, you only need to update the SharedPreferences and the rebuilds inside the stream builder will be made automatically.