0

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.

intweek
  • 7
  • 6

1 Answers1

0

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();
}

Peter Koltai
  • 8,296
  • 2
  • 10
  • 20