Skip to content

单例

在Flutter的开发过程中,一个完整的项目,几乎少不了的使用到单例模式,为什么这么说,如果你使用网络请求。那么你一定会基于Dio或者任何的网络请求库实现自己的请求类。对此你一定会用到单例。如果你并没有为所有的请求封装一个统一的请求类,或者即便实现也不使用单例,那么你大错特错。
单例可以帮助你减少一个类的构造函数重复的调用,同时可以节省不断new一个对象时,创建出的内存。
以我们的RequestClient类为示例,

dart
class RequestClient {
  final Dio _dio = Dio();

  // context
  final BuildContext? context;

  /// 是否自动添加 票据
  final bool autoAuthorization;
  RequestClient({this.context, this.autoAuthorization = true}) {
    /// 我们会在这里进行一些初始化操作,比如接口配置
    /// 此外还会添加请求时的interceptors,以及响应的interceptors
    /// 如果不使用单例,这些构造函数将不断地被重复初始化
  }

  /// ...get 方法封装
  /// ...post 方法封装
}

而当我们加入单例后,在来调用RequestClient时,我们只需要调用RequestClient.instance即可。

dart
class Request {
  /// 工厂模式
  static Request get instance => _getInstance();
  static Request? _instance;

  /// 后端并未处理无效token,所以只能前端保留2个实例在整个应用的生命周期
  RequestClient? client;

  Request._internal();

  static Request _getInstance() {
    _instance ??= Request._internal();

    return _instance!;
  }

  factory Request({BuildContext? context}) {
    if (_getInstance().client == null) {
      _getInstance().client =
          RequestClient(context: context, autoAuthorization: true);
    }

    return _getInstance();
  }

  void reset() {
    _getInstance().client = null;
  }
}

当上面的请求类通过下面的方式调用时,将不再被重复初始化

dart
Future<void> run()async {
  await Request().client!.get("url-1");
  await Request().client!.get("url-2");
}

run();

如何实现单例

在 Dart 的空安全特性下,可以使用 late 关键字和静态变量来创建一个空安全的单例模式。下面是一个示例代码:

dart
class Singleton {
  static late Singleton _instance;

  Singleton._();

  factory Singleton() {
    _instance ??= Singleton._();
    return _instance;
  }

  // 其他实例方法和属性...
}

在上述代码中,late 关键字用于初始化 _instance 变量。late 关键字表示该变量会延迟初始化,使得在构造函数调用时不需要立即给 _instance 赋值。通过使用 ??= 运算符,只有当 _instance 为空时才会进行实例化,从而保证只有一个实例被创建。

使用空安全的单例模式时,可以通过以下方式访问单例对象:

dart
var singleton = Singleton();

每次调用 Singleton() 都会返回同一个实例,即全局唯一的实例。

在 Dart 的空安全模式下,还可以使用 late 关键字配合 static 关键字来实现静态的空安全单例模式。示例如下:

dart
class Singleton {
  static late final Singleton _instance = Singleton._();

  Singleton._();

  static Singleton get instance => _instance;

  // 其他实例方法和属性...
}

在上述代码中,通过将 _instance 声明为 late final,并使用 static 修饰其访问器 instance,实现了一个静态的空安全单例模式。通过 Singleton.instance 可以访问到单例对象。

使用空安全的单例模式时,需要注意合理设计单例的初始化和使用方式,以避免空引用错误和不必要的实例化。空安全的特性能够在编译时帮助捕捉潜在的空引用异常,让代码更加健壮和可靠。

仅用于培训和测试,通过使用本站代码内容随之而来的风险与本站无关。版权所有,未经授权请勿转载,保留一切权利。
ICP备案号:滇ICP备15009214号-13   公安网备:滇公网安备 53312302000061号