5

Code content is not important. Just one problem timer can not dispose when I want to leave this page. When I leave from this page, sendMessage("message"); function continue to run. Is there any option to dispose this timer?

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();
}

The error is below.

EXCEPTION CAUGHT BY WIDGETS LIBRARY The following assertion was thrown while finalizing the widget tree: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 4182 pos 12: '_debugLifecycleState != _ElementLifecycle.defunct': is not true. Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause. In either case, please report this assertion by filing a bug on GitHub:

I use dispose timer, but it can not dispose timer. I could not solve this problem. Help, please.

Akif
  • 7,098
  • 7
  • 27
  • 53
SefaUn
  • 824
  • 1
  • 7
  • 23

3 Answers3

7

i findout issue after run your code, the main problem is, dispose is called on a widget when it is completely removed from the parent tree.

so when you route new page,

  1. Using push navigation, a new screen is added on top of current screen. hence the tree (of old screen) is not completely destroyed hence dispose is not called.
  2. using pop. the screen is removed so is the tree. hence dispose is called.
  3. using push replacement. new screen replaces old screen deleting the widget tree. so dispose is called.

and for code, try this. (main part is pushReplacement i am using this for navigation)

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

final code is,

 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"),
       );
      }
    }
Shirsh Shukla
  • 5,491
  • 3
  • 31
  • 44
3

I hope the above solution works fine for you but if not, then you can also try the below code because in my case the above solution does not works fine.

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;
      }
  }
Muhammad Tameem Rafay
  • 3,602
  • 2
  • 21
  • 32
2

Instead of dispose() try putting it in a deactivate().

Mayb3Not
  • 441
  • 4
  • 10