Flutter资源管理工具插件disposable_utils的使用

Flutter资源管理工具插件disposable_utils的使用

在Dart和Flutter中,没有一个统一的方法来释放对象资源。例如,StreamController.close()StreamSubscription.cancel() 和不同的 Flutter 对象中的 dispose() 方法都做着同样的事情——释放持有的信息。但它们并没有一个统一的接口。这就是 Disposable 的作用。

DisposableCollector 是一个可以组合多个可释放对象的集合,可以一次性释放它们。它还提供了扩展方法来简化流的操作。

你是否注意到以下问题?

在 Dart 和 Flutter 中,没有一个统一的方法来释放对象资源。例如:

class SomeDisposable {
  /// ...

  final _subscription = someStream.listen(
    (value) => doSomethingWith(value)
  );

  /// ...

  void dispose() {
    _subscription.cancel();
  }
}

使用 DisposableCollector 后,代码会变成这样:

class SomeDisposable extends DisposableCollector {
  /// ...
  someStream
    .listen((value) => doSomethingWith(value))
    .addTo(this);
  
  /// ...
}

你还可以通过工厂方法将任何对象转换为 Disposable

final disposable = Disposable.create(yourObject, () => yourObject.close());
// 或者
final disposable = yourObject.toDisposable(() => yourObject.close());

完整示例代码

以下是一个完整的示例代码,展示了如何使用 DisposableCollector 来管理资源:

import 'dart:async';
import 'package:disposable_utils/disposable_utils.dart';

void main() {
  final service = new DataService();
  final bloc = new Bloc(service);

  bloc.stream.listen(
    (v) => print(v),
    onDone: () => print("Complete")
  );

  bloc.dispose();

  // 你会看到打印出 "Complete",因为 bloc 在接收到数据服务的值之前已经被释放。
}

/// 模仿 BLoC 作为流的存储
class Bloc extends DisposableCollector {
  Stream<int> get stream => _streamController.stream;
  final StreamController<int> _streamController = new StreamController();

  Bloc(DataService service) {
    _streamController.addTo(this);

    /// 当然,你可以写成如下形式:
    /// ```
    /// final v = await service.getValue();
    /// _streamController.add(v);
    /// ````
    /// 或者
    /// ```
    /// _streamController.addStream(service.getValue().asStream());
    /// ```
    /// 但在这些情况下,如果你在获取未来/流的值之前释放了你的 StreamController,
    /// 你会看到不同的异常。但是当你使用 `addTo(Disposable)` 扩展方法时,
    /// 会在 StreamController 被释放时取消订阅流,不会抛出异常。

    service.getValue().asStream()
      .listen((v) => _streamController.add(v))
      .addTo(this);
  }
}

/// 模仿数据服务
class DataService {
  Future<int> getValue() async {
    await Future.delayed(Duration(seconds: 1));
    return 3;
  }
}

更多关于Flutter资源管理工具插件disposable_utils的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter资源管理工具插件disposable_utils的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


disposable_utils 是一个 Flutter 插件,用于管理资源的生命周期,确保在资源不再需要时能够正确地释放。这对于防止内存泄漏和资源浪费非常有用,特别是在处理需要手动释放的资源(如流、控制器、文件句柄等)时。

安装

首先,在 pubspec.yaml 文件中添加 disposable_utils 依赖:

dependencies:
  disposable_utils: ^1.0.0

然后运行 flutter pub get 来安装依赖。

基本用法

disposable_utils 提供了一个 Disposable 接口,任何需要手动释放的资源都可以实现这个接口。此外,它还提供了一个 DisposableBag 类,用于收集和管理多个 Disposable 对象。

1. 实现 Disposable 接口

假设你有一个自定义的资源类 MyResource,你可以通过实现 Disposable 接口来确保它能够被正确释放:

import 'package:disposable_utils/disposable_utils.dart';

class MyResource implements Disposable {
  // 假设这个资源需要在释放时关闭
  void close() {
    print('MyResource closed');
  }

  [@override](/user/override)
  void dispose() {
    close();
  }
}

2. 使用 DisposableBag 管理资源

DisposableBag 是一个容器,用于管理多个 Disposable 对象。当 DisposableBag 被释放时,它会自动释放所有添加到其中的资源。

import 'package:disposable_utils/disposable_utils.dart';

void main() {
  // 创建一个 DisposableBag
  final disposableBag = DisposableBag();

  // 创建一个资源并添加到 DisposableBag
  final resource1 = MyResource();
  disposableBag.add(resource1);

  // 创建另一个资源并添加到 DisposableBag
  final resource2 = MyResource();
  disposableBag.add(resource2);

  // 当不再需要这些资源时,释放 DisposableBag
  disposableBag.dispose();
}

在上面的例子中,当 disposableBag.dispose() 被调用时,resource1resource2 都会自动被释放。

3. 使用 DisposableBuilder 自动管理资源

DisposableBuilder 是一个小部件,用于在 Flutter 中自动管理资源的生命周期。它会在小部件被销毁时自动释放资源。

import 'package:flutter/material.dart';
import 'package:disposable_utils/disposable_utils.dart';

class MyWidget extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return DisposableBuilder(
      disposer: (disposableBag) {
        final resource1 = MyResource();
        disposableBag.add(resource1);

        final resource2 = MyResource();
        disposableBag.add(resource2);
      },
      builder: (context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Disposable Utils Example'),
          ),
          body: Center(
            child: Text('Resources are managed automatically'),
          ),
        );
      },
    );
  }
}
回到顶部