I have a list of objects that I am attempting to save
List<Exercise> todaysExercises = [];
//Load data from shared preferences
Future<void> loadData() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String? myDataString = prefs.getString('todaysExercises');
if (myDataString != null) {
final List<dynamic> myDataJson = jsonDecode(myDataString);
todaysExercises =
myDataJson.map((dynamic item) => Exercise.fromMap(item)).toList();
}
}
// Save Todays exercieses to shared preferences
Future<void> saveData() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final List<dynamic> myDataJson =
todaysExercises.map((Exercise exercise) => exercise.toMap()).toList();
final String myDataString = jsonEncode(myDataJson);
await prefs.setString('todaysExercises', myDataString);
}
@override
void initState() {
super.initState();
loadData();
}
Prior to clicking add exercise:
After clicking add exercise, calling SaveData():
I do not understand why initState is not calling loadData() correctly. If my understanding is correct it should set todays exercises to the saved date prior to my use of TodaysExercises when passing it to my ExerciseList().
ExerciseList(
userExercises: todaysExercises,
editFunction: _showEditDialog,
),
I'm very new to shared preferences so thank you for the help!
That's because when initState
is called, loadData
is invoked, but it does not block the execution of initState
. This means that the widget continues to build BEFORE loadData
has finished loading the data from SharedPreferences. As a result, the widget is built with the initial empty data BEFORE the data is loaded from SharedPreferences.
To fix this issue, you can use a FutureBuilder
to wait for the data to be loaded before building the widget. Here's an example of how to use FutureBuilder to solve this issue.
I do not know what your code looks like, but take this as an example of what I mean:
FutureBuilder<List<Exercise>>(
future: loadData(),
builder: (BuildContext context, AsyncSnapshot<List<Exercise>> snapshot) {
if (snapshot.hasData) {
// Use the loaded data here
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data![index].name),
subtitle: Text(snapshot.data![index].description),
);
},
);
} else {
// Show a loading indicator while the data is loading
return Center(child: CircularProgressIndicator());
}
},
);