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

  • 相关阅读:
    新手也能上手的天气预报demo(高德API+echarts)
    SQL必需掌握的100个重要知识点:使用视图
    解决全屏不了的问题状态栏依然存在
    Java 21:最新特性、性能改进和语言发展
    数据结构:栈和队列
    Docker--harbor私有仓库部署与管理
    5.0、C语言数据结构——线性表 ( 2 )
    详解FreeRTOS:二值信号量和计数信号量(高级篇—2)
    ROS问题汇总以及vscode配置问题
    【通信】Matlab实现改进的多同步压缩变换
  • 原文地址:https://blog.csdn.net/u013113678/article/details/139575454