So I have created a class for using shared_preferences
with a singleton pattern, so I can use one instance across all my files.
And almost all of the time it works flawlessly, but occasionally, when I am not using the app but it is still open in the background, and then open it, I get a gray screen because my _prefs
can't get the data (probably because it isn't initialized). I can't debug test it because it only appears in release mode.
I am not using any more methods from shared_preferences
, like SharedPreferences.clear()
or SharedPreferences.setMockInitialValues({});
. Also, I am only initializing them in my main() function (code given below).
I am wondering if I am doing something wrong, not correctly initializing it or not checking if it is initialized before setting and retrieving data. Does anyone have any clue what may be wrong? Maybe I need to take a different approach?
custom class:
class SharedUserData {
// home screen dailies
static const String _APP_CURRENT_DATA_SEED = 'app_current_data_seed';
static const String _CHOSEN_DAILY_PHYSICS_QUESTION_ANSWER_INDEX= 'chosen_daily_physics_question_index';
SharedPreferences? _prefs;
// SINGLETON
SharedUserData._privateConstructor();
static final SharedUserData _instance = SharedUserData._privateConstructor();
static SharedUserData get instance => _instance;
Future<void> init() async {
_prefs = await SharedPreferences.getInstance();
}
void initializeHomeScreenDailies() {
int? writtenDateSeed = readCurrentDataSeed();
int calculatedDateSeed = calculateCurrentDateSeed();
if(writtenDateSeed == null || writtenDateSeed != calculatedDateSeed) {
writeCurrentDataSeed(calculatedDateSeed);
writeChosenDailyPhysicsQuestionAnswerIndex(-1);
}
printAllData();
}
// READ METHODS
int? readCurrentDataSeed() {
assert(_prefs != null, 'SharedPreferences not initialized. Call init() first.');
return _prefs!.getInt(_APP_CURRENT_DATA_SEED);
}
int? readChosenDailyPhysicsQuestionAnswerIndex() {
assert(_prefs != null, 'SharedPreferences not initialized. Call init() first.');
return _prefs!.getInt(_CHOSEN_DAILY_PHYSICS_QUESTION_ANSWER_INDEX);
}
// WRITE METHODS
Future<void> writeCurrentDataSeed(int currentDataSeed) async {
assert(_prefs != null, 'SharedPreferences not initialized. Call init() first.');
await _prefs!.setInt(_APP_CURRENT_DATA_SEED, currentDataSeed);
}
Future<void> writeChosenDailyPhysicsQuestionAnswerIndex(int chosenDailyPhyscisQuestionAnswerIndex) async {
assert(_prefs != null, 'SharedPreferences not initialized. Call init() first.');
await _prefs!.setInt(_CHOSEN_DAILY_PHYSICS_QUESTION_ANSWER_INDEX, chosenDailyPhyscisQuestionAnswerIndex);
}
}
I am initializing it in my main.dart
file like so:
void main() {
initializeSharedPreferences();
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
void initializeSharedPreferences() async {
WidgetsFlutterBinding.ensureInitialized();
await SharedUserData.instance.init();
SharedUserData.instance.initializeHomeScreenDailies();
}
And using like (in a function):
final int? seed = SharedUserData.instance.readCurrentDataSeed();
I tried researching it only but it seems like I can't find anywhere where this problem had also occured.
Since you call an async
function from main
, you should make main
also async
and use await
to wait for initializeSharedPreferences
to complete.
Try this:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initializeSharedPreferences();
runApp(MyApp());
}
Future<void> initializeSharedPreferences() async {
await SharedUserData.instance.init();
SharedUserData.instance.initializeHomeScreenDailies();
}