【问题标题】:Periodic Timer can not disposePeriodic Timer 无法处理
【发布时间】:2021-03-21 04:40:36
【问题描述】:

代码内容并不重要。当我想离开这个页面时,只有一个问题计时器无法处理。当我从这个页面离开时,sendMessage("message"); 函数继续运行。有没有办法处置这个计时器?

Timer timer;

@override
void initState() {
super.initState();
timer = Timer.periodic(new Duration(seconds: 5), (timer) async {
          setState(() {
            unicode++;
            unicodeString = unicode.toString();
            if (unicodeString.length < 6) {
              int different = 6 - unicodeString.length;
              for (var i = 0; i < different; i++) {
                unicodeString = "0" + unicodeString;
              }
            }
            sendMessage("meesage");
              showSnackBarWithKey("Message Sended !");
          });
    });
}
 @override
 void dispose() {
 timer.cancel();
 super.dispose();
}

错误如下。

小部件库发现的异常 在最终确定小部件树时引发了以下断言: 'package:flutter/src/widgets/framework.dart':断言失败:第 4182 行 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct':不正确。 要么断言表明框架本身有错误,要么我们应该提供实质性的 此错误消息中的更多信息可帮助您确定和修复根本原因。 无论哪种情况,请通过在 GitHub 上提交错误来报告此断言:

我使用了dispose timer,但它不能dispose timer。我无法解决这个问题。请帮忙。

【问题讨论】:

  • 重要的是提供一个可以运行测试问题的最小完整可重现代码。
  • 您确定没有多次创建周期性Timer
  • 是的,我确定,我只是在initState();@jamesdlin 中创建了一个定期计时器
  • timer 是实例变量还是全局变量?从您发布的代码中无法分辨。另外,请实际验证是否只创建了一个Timer,而不是依赖可能是错误的假设
  • 什么时候我想离开这个页面。 - 你能提供更多关于你如何离开这个页面的信息吗?

标签: flutter dart


【解决方案1】:

我在运行您的代码后发现问题, 主要问题是, 当一个小部件从父树中完全移除时调用 dispose。

所以当你路由新页面时,

  1. 使用推送导航,在当前屏幕之上添加一个新屏幕 屏幕。因此(旧屏幕的)树没有被完全摧毁 因此没有调用 dispose。
  2. 使用流行音乐。屏幕被移除,树也被移除。因此处置是 调用。
  3. 使用推送替换。新屏幕替换旧屏幕删除 小部件树。所以调用了 dispose。

对于代码, 尝试这个。 (主要部分是 pushReplacement 我正在使用它进行导航)

Navigator.pushReplacement(
               context, MaterialPageRoute(builder: (context) => SplashScreen()));

最终代码是,

 class TimerButton extends StatefulWidget {
      @override
      _TimerButtonState createState() => _TimerButtonState();
    }
    
    class _TimerButtonState extends State<TimerButton> {
      Timer _timer;
      @override
      void initState() {
        super.initState();
    
        _timer = Timer.periodic(new Duration(seconds: 5), (timer)  async{
          setState(() {
           /* unicode++;
            unicodeString = unicode.toString();
            if (unicodeString.length < 6) {
              int different = 6 - unicodeString.length;
              for (var i = 0; i < different; i++) {
                unicodeString = "0" + unicodeString;
              }
            }*/
            sendMessage("meesage");
            showSnackBarWithKey("Message Sended !");
          });
        });
      }
      @override
      void dispose() {
        _timer.cancel();
        super.dispose();
      }
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
       return RaisedButton(
         onPressed: (){
           Navigator.pushReplacement(
               context, MaterialPageRoute(builder: (context) => SplashScreen()));
         },
         child: Text("data"),
       );
      }
    }

【讨论】:

    【解决方案2】:

    尝试将其放入deactivate(),而不是dispose()

    【讨论】:

      【解决方案3】:

      我希望上述解决方案对您有用,但如果没有,您也可以尝试以下代码,因为在我的情况下,上述解决方案无法正常工作。

      static Timer timerObjVar;
       static Timer timerObj;
      
         timerObj = Timer.periodic(Duration(seconds: 10), (Timer timer) async {
            timerObjVar = timer;
            _initData();  
         });
          
       // when you want to cancel the timer call this function
        cancelTimer() {
      
            if (timerObjVar != null) {            
              timerObjVar.cancel();
              timerObjVar = null;
            }
      
            if (timerObj != null) {           
              timerObj.cancel();
              timerObj = null;
            }
        }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多