如何在飞镖中实现具有异步初始化和空安全的单例?

How to implement a singleton with async initialisation and null safety in dart?

我需要一个用于共享首选项的单例,它具有异步初始化但也适用于空安全。通常我使用以下单例实现,但是拥有空安全的单例的最佳方法是什么?

class SharedPrefs {
static SharedPrefs _instance;
static Future<Null> _mutex;

static Future<SharedPrefs> getInstance() async {
  if (_mutex != null) {
    await _mutex;
  }
  var completer = Completer<Null>();
  _mutex = completer.future;

  if (_instance == null) {
    _instance = SharedPrefs();
    await _instance.init();
  }

  completer.complete();
  _mutex = null;

  return _instance;
}

SharedPreferences prefs;

SharedPrefs();

Future<SharedPrefs> init() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  return this;
}

dynamic get(String key) {
  return prefs.getString(key);
}

Future<bool> put(String key, dynamic value) async {
  return await prefs.setString(key,value);
}
}

给你:

class SharedPreferencesProvider {
  static SharedPreferencesProvider? _instance;
  final SharedPreferences _sharedPreferences;

  static Future<SharedPreferencesProvider> getInstance() async {
    if (_instance == null) {
      final sharedPreferences = await SharedPreferences.getInstance();
      _instance = SharedPreferencesProvider._(sharedPreferences);
    }
    return _instance!;
  }

  SharedPreferencesProvider._(SharedPreferences sharedPreferences)
      : _sharedPreferences = sharedPreferences;

init-first 单例

class Singleton {
  late Map<String,String> obj;

  Db._();
  static Db? _instance;
  static Db get inst => _instance ??= Db._();
  init () async {
    // await ...
    obj = {'a': 1};
  }
}

void main () async {
  // put init first
  await Db.inst.init();

  // your other code
  // your other code

  print(Db.inst.obj);

  // your other code
  // your other code


}

我在所有语言中都使用这种方法,稳定且易于理解。

一个测试示例

db.dart

import 'package:mongo_dart/mongo_dart.dart' as Mongo;

class Db {
  late Mongo.DbCollection test;

  Db._();
  static Db? _instance;
  static Db get inst => _instance ??= Db._();
  init () async {
    var db = Mongo.Db("mongodb://localhost:27017/");
    await db.open();
    test = db.collection('test');
  }
}

test.dart

import 'package:mj_desk_server/db.dart';

void main () async {
  
  await Db.inst.init();
  
  myApp();
}

myApp () async {
  // do anything
  // do anything
  // do anything
  print(await Db.inst.test.find().toList());
  print('ok');
}