前言

开发flutter一般会用状态管理工具,用了状态管理后大部分控件都会是StatelessWidget,StatefulWidget有dispose重载获取控件销毁时机,但StatelessWidget则没有,此时我们要获取控件销毁的时机就需要另寻他法了。


一、什么是dispose探测控件?

这是一个控件用于帮助探测无状态控件的销毁时机,有点类似visibility_detector用于探测控件的显示和隐藏。

1、通常情况

通常情况下想要知道一个页面是否销毁或切换了,需要通过StatefulWidget的dispose方法获取。代码如下:

class Page extends StatefulWidget {
  const Page({
    super.key,
  });
  
  _Page createState() => _Page();
}

class _Page<T extends Widget, S> extends State<Page> {
  
  void dispose() {
    super.dispose();
    //此处获取到dispose时机
    
  }
  
  
  void didUpdateWidget(covariant Page oldWidget) {
    super.didUpdateWidget(oldWidget);
    //此处获取到控价刷新时机

  }
  
  
  Widget build(BuildContext context) {
    return const SizedBox();
  }
}

2、使用dispose探测控件

在使用使用状态管理的情况下,通常都是StatelessWidget页面,将其改成StatefulWidget,分成两个类显然是麻烦的。如果有了DisposeDetector(dispose探测控件),作为一个控件放入StatelessWidget页面中,就可以直接获取到dispose时机了。

class Page2 extends StatelessWidget {
  const Page2({
    super.key,
  });
  
  Widget build(BuildContext context) {
    return DisposeDetector(
      child: const SizedBox(),
      onDispose: () {
        //此处获取到dispose时机
      },
      onDidUpdateWidget: (DisposeDetector<SizedBox, dynamic> oldWidget) {
        //此处获取到控价刷新时机
      },
    );
  }
}

二、如何实现

1、继承StatefulWidget

在这里插入图片描述
在这里插入图片描述

2、定义dipose回调

在这里插入图片描述

3、定义child

在这里插入图片描述

4、重载Dispose方法

在这里插入图片描述

5、build child

在这里插入图片描述

三、完整代码

dispose_detector.dart

import 'package:flutter/material.dart';

/// 创建人:  xin
/// 创建时间: 2023/6/15 13:44
/// 注释: 销毁探测控件
class DisposeDetector<T extends Widget, S> extends StatefulWidget {
  final Function onDispose;
  final Function(DisposeDetector<T, S> oldWidget) onDidUpdateWidget;
  final T child;
  final S? tag; //自定义数据
  const DisposeDetector({super.key, 
    required this.child,
    required this.onDispose,
    required this.onDidUpdateWidget,
    this.tag,
  });
  
  _DisposeDetector<T, S> createState() => _DisposeDetector<T, S>();
}

class _DisposeDetector<T extends Widget, S> extends State<DisposeDetector<T, S>>
    with TickerProviderStateMixin {
  
  void dispose() {
    super.dispose();
    widget.onDispose();
  }

  
  void didUpdateWidget(covariant DisposeDetector<T, S> oldWidget) {
    super.didUpdateWidget(oldWidget);
    widget.onDidUpdateWidget(oldWidget);
  }

  
  Widget build(BuildContext context) {
    return widget.child;
  }
}

四、使用示例

1、基本用法

class Page2 extends StatelessWidget {
  const Page2({
    super.key,
  });
  
  Widget build(BuildContext context) {
    return DisposeDetector(
      child: const SizedBox(),
      onDispose: () {
        //此处获取到dispose时机
      },
      onDidUpdateWidget: (DisposeDetector<SizedBox, dynamic> oldWidget) {
        //此处获取到控价刷新时机
      },
    );
  }
}

2、设置定义数据

class Page2Controller {
  void dispose() {
    //销毁逻辑
  }
}

class Page2 extends StatelessWidget {
  final _ctrl = Page2Controller();
  Page2({
    super.key,
  });
  
  Widget build(BuildContext context) {
    return DisposeDetector(
      tag: _ctrl, //自定义数据,记录当前的controller
      onDispose: () {
        //此处获取到dispose时机
        _ctrl.dispose();
      },
      onDidUpdateWidget:
          (DisposeDetector<SizedBox, Page2Controller> oldWidget) {
        //此处获取到控价刷新时机
        if (oldWidget.tag != _ctrl)
        //如果刷新控件时controller改变了,则销毁旧controller
        {
          oldWidget.tag!.dispose();
        }
      },
      child: const SizedBox(),
    );
  }
}

总结

以上就是今天要讲的内容,本文提供的控件是比较有用的,尤其是业务逻辑有数据释放的需求,比如播放器之类的,控件销毁后需要结束播放,将播放资源销毁,如果是用StatelessWidget则没办法实现,用StatefulWidget又会使得页面实现变得麻烦或者复杂,最好的方法则是使用本文提供的dispose探测控件。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部