Flutter资源清理插件dispose_all的使用

Flutter资源清理插件dispose_all的使用

特性

  • DisposableObject 混入。使任何自定义类或从其他包实现的类能够与本包一起使用(并可被释放)。
  • disposeAll 方法用于 Iterable,可以释放其中的所有项目。这些项目可以是:
    • DisposableObject 显然可以。
    • ChangeNotifier 及其扩展或混入的任何内容,例如 TextEditingControllerFocusNodeScrollController 等等。
    • Sink,例如 StreamController
    • StreamSubscription
    • Timer
    • AnimationEagerListenerMixin,例如 AnimationController

使用

处理对象列表的清理

定义需要稍后释放的对象:

final textEditingController = TextEditingController();
final focusNode = FocusNode();
final stream = StreamController.broadcast();
final listener = someStream.listen(...);
final timer = Timer.periodic(...);
final animationController = AnimationController(...);

将它们放入一个可迭代对象中:

final disposables = [
  textEditingController,
  focusNode,
  stream,
  listener,
  timer,
  animationController,
];

当不再需要这些对象时,释放它们:

disposables.disposeAll();

使自定义类可释放

默认情况下,自定义类实例不能通过 disposeAll 方法进行释放。幸运的是,可以通过 DisposableObject 混入轻松添加此类功能:

class DisposableTest with DisposableObject {
  bool disposed = false; // 或者你需要的任何东西

  [@override](/user/override)
  void disposeObject() {
    disposed = true; // 或者你想执行的任何操作
  }
}

现在 DisposableTest 类的对象可以通过 disposeAll 方法进行释放:

final myDisposable = DisposableTest();
...
[
  myDisposable,
  ...
].disposeAll();

假设你使用了 Dio 包来处理 HTTP 请求,并且可能使用了 CancelToken 对象来取消请求。调用 disposeAll 方法在一个包含 CancelToken 的列表上会导致抛出 UnimplementedError。但你可以轻松地为 CancelToken 创建一个包装器使其正常工作:

import 'package:dio/dio.dart';

class CancelTokenDisposable extends CancelToken with DisposableObject {
  [@override](/user/override)
  void disposeObject() {
    cancel();
  }
}

现在 CancelTokenDisposable 实例可以通过 disposeAll 方法进行释放:

class _MyWidgetState extends State<MyWidget> {
  List _disposables = [];

  CancelTokenDisposable cancelToken = CancelTokenDisposable();

  [@override](/user/override)
  void initState() {
    super.initState();
    _disposables = [
      cancelToken,
      ...
    ];
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    ...
  }

  [@override](/user/override)
  void dispose() {
    _disposables.disposeAll();
    super.dispose();
  }
}

贡献

如果您觉得此包缺少您的项目所需的某些功能,请随时在 GitHub 上打开一个 issue。


完整示例

import 'dart:async';

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: FirstPage(),
    );
  }
}

class FirstPage extends StatelessWidget {
  const FirstPage({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('dispose_all'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () => Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const SecondPage()),
          ),
          child: const Text('Go'),
        ),
      ),
    );
  }
}

class SecondPage extends StatefulWidget {
  const SecondPage({super.key});

  [@override](/user/override)
  State<SecondPage> createState() => _SecondPageState();
}

class _SecondPageState extends State<SecondPage> {
  // 用于该屏幕的可释放对象列表
  List _disposables = [];

  // 实际上可以释放的对象
  final TextEditingController _inputController = TextEditingController();
  late Timer _timer;

  int _seconds = 0;

  [@override](/user/override)
  void initState() {
    super.initState();
    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      setState(() {
        ++_seconds;
      });
    });

    // 初始化可释放对象列表
    _disposables = [
      _inputController,
      _timer,
    ];
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('dispose_all'),
      ),
      body: Column(
        children: [
          TextField(
            controller: _inputController,
            onChanged: (_) => setState(() {}),
          ),
          Text(_inputController.text),
          Text('秒数: $_seconds'),
        ],
      ),
    );
  }

  [@override](/user/override)
  void dispose() {
    // 通过 disposeAll 方法轻松释放所有可释放对象
    _disposables.disposeAll();
    super.dispose();
  }
}

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

1 回复

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


dispose_all 是一个用于 Flutter 的插件,旨在帮助开发者在不需要时自动释放资源。它通过自动管理各种可释放对象的生命周期,简化了资源管理的流程,减少了内存泄漏的风险。

安装

首先,你需要在 pubspec.yaml 文件中添加 dispose_all 依赖:

dependencies:
  dispose_all: ^1.0.0  # 请使用最新版本

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

基本用法

dispose_all 提供了一个 DisposeAll 类,你可以使用它来管理需要释放的资源。以下是一个简单的示例:

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

class MyWidget extends StatefulWidget {
  [@override](/user/override)
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  final DisposeAll _disposeAll = DisposeAll();

  [@override](/user/override)
  void initState() {
    super.initState();

    // 添加需要释放的资源
    final streamController = StreamController<int>();
    _disposeAll.add(streamController);

    final timer = Timer.periodic(Duration(seconds: 1), (timer) {
      print('Timer tick');
    });
    _disposeAll.add(timer);
  }

  [@override](/user/override)
  void dispose() {
    // 释放所有资源
    _disposeAll.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Container();
  }
}

主要功能

  1. 添加可释放对象: 使用 _disposeAll.add() 方法将需要释放的对象添加到 DisposeAll 实例中。支持的对象类型包括:

    • StreamController
    • Timer
    • ChangeNotifier
    • ValueNotifier
    • AnimationController
    • 任何实现了 Disposable 接口的自定义对象
  2. 释放所有资源: 在 dispose() 方法中调用 _disposeAll.dispose() 来释放所有已添加的资源。

  3. 自动释放: 当 DisposeAll 实例被释放时,它会自动释放所有已添加的资源,即使你没有显式调用 dispose() 方法。

自定义可释放对象

你可以通过实现 Disposable 接口来创建自定义的可释放对象:

class MyDisposable implements Disposable {
  [@override](/user/override)
  void dispose() {
    // 自定义释放逻辑
    print('MyDisposable disposed');
  }
}

// 添加到 DisposeAll
_disposeAll.add(MyDisposable());
回到顶部