You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart中单例构造函数传入不同参数时如何重建实例?

实现方案

你原来的实现是全局固定唯一实例,要实现传入不同参数新建实例、支持销毁旧实例的需求,改用参数作为Key的缓存Map来管理实例即可,修改后代码如下:

import 'package:flutter/foundation.dart';

class Foo extends ChangeNotifier {
  // 改为final避免实例的channel被意外修改
  final String channel;

  void instanceMemberFunction () {
      print('Foo created with channel $channel');
  }

  // 用Map缓存不同channel对应的实例
  static final Map<String, Foo> _instanceCache = {};

  // 私有构造方法,初始化时直接传入channel
  Foo._internal({required this.channel}) {
    instanceMemberFunction();
  }

  factory Foo({required String channel}) {
    // 对应channel的实例已存在,直接返回缓存
    if (_instanceCache.containsKey(channel)) {
      return _instanceCache[channel]!;
    }
    // 不存在则新建实例存入缓存后返回
    final newInstance = Foo._internal(channel: channel);
    _instanceCache[channel] = newInstance;
    return newInstance;
  }

  // 销毁指定channel对应的实例
  static void disposeInstance(String channel) {
    if (_instanceCache.containsKey(channel)) {
      // 先执行ChangeNotifier的资源清理逻辑
      _instanceCache[channel]?.dispose();
      _instanceCache.remove(channel);
    }
  }

  // 可选:销毁所有缓存的实例
  static void disposeAll() {
    _instanceCache.forEach((_, instance) => instance.dispose());
    _instanceCache.clear();
  }
}

使用示例

// 首次调用bar参数,新建实例
final foo1 = Foo(channel: "bar");
// 再次调用相同bar参数,返回已有实例
final foo2 = Foo(channel: "bar");
print(foo1 == foo2); // 输出 true

// 调用不同baz参数,新建实例
final foo3 = Foo(channel: "baz");
print(foo1 == foo3); // 输出 false

// 销毁bar参数对应的旧实例
Foo.disposeInstance("bar");
// 销毁后再次调用bar参数,会创建新的实例
final foo4 = Foo(channel: "bar");
print(foo1 == foo4); // 输出 false

注意事项

  • 如果你的区分依据不止channel一个参数,可以把多个参数封装成一个自定义对象作为Map的Key,只要保证相同参数的Key相等即可。
  • 从缓存中移除的实例没有其他地方引用时,Dart的垃圾回收会自动回收其占用的内存。

内容的提问来源于stack exchange,提问作者Aditya Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 08:06:00