带有 shared_preferences 的 Flutter Null 安全配置类

问题描述

Flutter 1.x 中,我使用 Flutter shared_preferences 包实现了一个 Config 类;代码如下所示:

import 'package:shared_preferences/shared_preferences.dart';

class Config {
  static final Config _config = Config._internal();

  factory Config() => _config;

  final accesstokenKey = 'accesstoken';
  String _accesstoken;

  SharedPreferences prefs;

  Config._internal() {
    loadData();
  }

  void loadData() async {
    prefs = await SharedPreferences.getInstance();
    _accesstoken = prefs.getString(accesstokenKey) ?? '';
  }

  String get accesstoken {
    return _accesstoken;
  }

  set accesstoken(String accesstoken) {
    _accesstoken = accesstoken;
    _saveString(accesstokenKey,accesstoken);
  }

  _saveString(String key,String value,{String printValue = ''}) {
    String printVal = printValue.length > 0 ? printValue : value;
    prefs.setString(key,value);
  }

}

我正在 Flutter 2.x 中创建一个新项目并尝试使用相同的代码,但由于与空安全相关的更改,我在正确获取更新后的代码时遇到了一些困难。 包的更新文档说要像这样初始化 _prefs 对象:

Future<SharedPreferences> _prefs = SharedPreferences.getInstance();

然后使用以下方法创建本地偏好设置对象:

final SharedPreferences prefs = await _prefs;

这很好,但我不想让每个使用 shared_preferences 的类方法都异步然后重新创建变量。同时,如果不先初始化它,我就无法将其创建为类变量。有人可以告诉我一种更干净的方法来做到这一点,还是每次使用时我都必须重新声明它? 另外,如何在其他类中初始化配置对象?在我的 1.x 代码中,我会这样做:

final Config config = new Config();

然后开始访问配置对象的属性。我现在如何使用类中的所有异步代码对其进行初始化?

这里是今天更新的代码

import 'package:shared_preferences/shared_preferences.dart';

import '../models/device.dart';

class Config {
  static final Config _config = Config._internal();

  factory Config() => _config;

  final accesstokenKey = 'accesstoken';

  String _accesstoken = '';

  Future<SharedPreferences> _prefs = SharedPreferences.getInstance();

  Config._internal() {
    print('Config constructor');
    loadData();
  }

  Future<void> loadData() async {
    final SharedPreferences prefs = await _prefs;
    _accesstoken = prefs.getString(accesstokenKey) ?? '';
  }

  String get accesstoken {
    return _accesstoken;
  }

  set accesstoken(String accesstoken) {
    _accesstoken = accesstoken;
    _saveString(accesstokenKey,{String printValue = ''}) {
    String printVal = printValue.length > 0 ? printValue : value;
    print('Config: _saveString("$key","$printVal")');
    final SharedPreferences prefs = await _prefs;
    prefs.setString(key,value);
  }

}

解决方法

如果在获取类的实例之前需要等待一些异步工作完成,请考虑使用静态方法(而不是 factory 构造函数,因为构造函数必须始终返回基类型)。

您可以使用 late 字段来允许它们在初始化之前为非空:

class Config {

  late String _accessToken;
  String get accessToken => _accessToken;

  Config._();  // private constructor to prevent accidental creation

  static Future<Config> create() async {
    final config = Config();
    final preferences = await SharedPreferences.getInstance();
    config._accessToken = await preferences.getString('<your key>');
    return config;
  }
}

如果您想确保在运行您的应用之前对其进行初始化,您可以在调用 main() 以将控制权交给 Flutter 框架之前在您的 runApp() 方法中对其进行初始化:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();  // make sure all plugins loaded etc.
  final config = await Config.create();
  print(config.accessToken);
  runApp(MyApp());
}
,

您可以在 SharedPreferences 方法中将 init 的实例作为静态字段获取:

static SharedPreferences? _prefs; //or: static late SharedPreferences _prefs;

static init() async {
  _prefs = await SharedPreferences.getInstance();
}

并在第一次小部件运行的 init() 方法中调用 build() 一次。现在您可以随心所欲地在任何地方使用 _prefs。 如果我想向您展示一个完整的类来使用 SharedPreferences,它看起来像这样:

import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesRepository {
  static SharedPreferences? _prefs;

  static init() async {
    _prefs = await SharedPreferences.getInstance();
  }

  static putInteger(String key,int value) {
    if (_prefs != null) _prefs!.setInt(key,value);
  }

  static int getInteger(String key) {
    return _prefs == null ? 0 : _prefs!.getInt(key) ?? 0;
  }

  static putString(String key,String value) {
    if (_prefs != null) _prefs!.setString(key,value);
  }

  static String getString(String key) {
    return _prefs == null ? 'DEFAULT_VALUE' : _prefs!.getString(key) ?? "";
  }

  static putBool(String key,bool value) {
    if (_prefs != null) _prefs!.setBool(key,value);
  }

  static bool getBool(String key) {
    return _prefs == null ? false : _prefs!.getBool(key) ?? false;
  }
}

希望这对你有用。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...