• Flutter 实现dispose探测控件



    前言

    开发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探测控件。

  • 相关阅读:
    .NET软件开发工程师面试题
    Python实现自动重新运行指定python脚本
    我的研究生论文的小总结 (以多标签方向为例)
    振弦采集仪应用水坝安全监测的方案
    tidb-系统内核调优及对比
    两数之和(Java版)
    Open3D Ransac拟合空间直线(python详细过程版)
    cmake链接ffmpeg静态库的方法,及报错答解
    【API篇】三、转换算子API(上)
    网安学习-应急响应1
  • 原文地址:https://blog.csdn.net/u013113678/article/details/139575454