Flutter: синглтон с общими настройками не инициализируется должным образом - PullRequest
0 голосов
/ 28 мая 2020

Я очень новичок во Flutter и Dart, прихожу с android, принеся с собой некоторые из моих привычек, я хочу реализовать одноэлементный объект SharedPreferences, чтобы упростить и избежать повторения (дублирования). это мой одноэлементный класс SharedPreferences:

import 'package:shared_preferences/shared_preferences.dart';
import 'package:synchronized/synchronized.dart';

class MySharedPreferences {
  static MySharedPreferences _instance;
  SharedPreferences _preferences;

  // keys
  final String _logged = "LOGGED";
  final String _accessToken = "ACCESS_TOKEN";

  MySharedPreferences._() {
    _initSharedPreferences();
  }

  static MySharedPreferences getInstance() {
    var lock = new Lock();
    if (_instance == null) {
      lock.synchronized(() => {_instance = new MySharedPreferences._()});
      return _instance;
    } else
      return _instance;
  }

  _initSharedPreferences() async {
    _preferences = await SharedPreferences.getInstance();
  }

  bool checkLogged() {
    return _preferences.getBool(_logged);
  }

  void setLogged(bool logged) {
    _preferences.setBool(_logged, logged);
  }

ну, большая часть этого logi c - это то, что я делал в android, и работал отлично, но когда я попробовал его протестировать, синглтон всегда имеет значение null, вот тест:

import 'package:flutter_test/flutter_test.dart';
import 'package:reportingsystem/local/my_shared_preferences.dart';

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();
  test('Test the shared_preferences', () {
    MySharedPreferences preferences = MySharedPreferences.getInstance();
    preferences.setLogged(true);
    expect(preferences.checkLogged(), true);
    preferences.setLogged(false);
    expect(preferences.checkLogged(), false);
  });
}

Тест не проходит, потому что объект "предпочтения" имеет значение null, я не знаю, что не так, и я не нахожу много об этом в документации . вот трассировка стека:

dart:core                                                       Object.noSuchMethod
package:reportingsystem/local/my_shared_preferences.dart 34:18  MySharedPreferences.setLogged
test\shared_preferences_test.dart 8:17                          main.<fn>
test\shared_preferences_test.dart 6:39                          main.<fn>

NoSuchMethodError: The method 'setBool' was called on null.
Receiver: null
Tried calling: setBool("LOGGED", true)

1 Ответ

2 голосов
/ 28 мая 2020

Вот пример, в котором вы должны вызвать init при первом вызове синглтона, и тогда вы сможете получить к нему доступ синхронно.

class MySharedPreferences {
  static final MySharedPreferences _instance = MySharedPreferences._internal();
  MockSharedPreferences prefereces;
  factory MySharedPreferences() {
    return _instance;
  }

  Future<void> init() async {
    if (prefereces != null) {
      return;
    }
    prefereces = await Future.delayed(Duration(seconds: 1), () => MockSharedPreferences());
  }

  MySharedPreferences._internal();
}

class MockSharedPreferences {
  final Map<String, bool> data = {};
  void setBool(String key, bool value) {
    data[key] = value;
    print('data $data');
  }
}

Тогда вы можете использовать его без await после первая инициализация, например:

Future<void> main() async {
      await first();
      anyOther();
}

void anyOther() {
  MySharedPreferences singleton = MySharedPreferences();
  singleton.prefereces.setBool('first', true);
}

Future<void> first() async {
  MySharedPreferences singleton = MySharedPreferences();
  await singleton.init();
  singleton.prefereces.setBool('notFirst', true);
}
...