setState() called after Dispose()

Asked

Viewed 155 times

1

I am receiving this log in my application flutter after integrating google maps.

I declared it right at the beginning of the code

    CameraPosition _posicaoCamera = CameraPosition(
      target: LatLng(-23.562436, -46.655005),
      zoom: 18
  );

And this is my setState that is getting the error:

    _adicionarListenerLocalizacao(){

    //-23.579934, -46.660715

    var geolocator = Geolocator();
    var locationOptions = LocationOptions(accuracy: LocationAccuracy.high);
    geolocator.getPositionStream( locationOptions ).listen((Position position){

      setState(() {
        _posicaoCamera = CameraPosition(
            target: LatLng(position.latitude, position.longitude),
            zoom: 18
        );
        _movimentarCamera();
      });

    });

  }
  • Where is this setState being called? The error says that this line is being called at a time when this widget no longer exists.

  • No problem, I will write an answer to try to help with your problem. I ask you to edit your question and include the function _adicionarListenerLocalizacao whole. Relying on external links is not the purpose of this site and correcting it will help the next people who have the same question .

  • 1

    Thank you for the tip

1 answer

2


This error occurs because you are calling the code setState after the Widget in question has been discarded.

Why does this happen? You used the method listen to listen to a GPS position stream. Whenever there is a position variation, the setState callback will be called, even when this widget is no longer on the screen.

To solve this, there are two solutions:

  • Save Subscription to a class variable and cancel it when this Widget is destroyed:
var subscription;
[...]
_adicionarListenerLocalizacao(){
    subscription = geolocator.getPositionStream( locationOptions ).listen((Position position){[...]});
    [...]
}
 @override
  void dispose() {
    subscription.cancel();
    super.dispose();
  }

That way you stop listening for variations of position after this method has been called.

Or:

  • Check if widget exists before calling setState:
if (this.mounted){
 setState((){
      _posicaoCamera = CameraPosition(
        target: LatLng(position.latitude, position.longitude),
        zoom: 18
    );
    _movimentarCamera();
 });
}

I recommend the first option, as you should stop listening to events when you are no longer going to make use of them.

The reason why the first solution is the most recommended is to prevent your app from suffering from Memory Leaks, after a certain amount of times a user visits the same page, if the subscriptions made are not canceled they remain in memory occupying more and more space, until the moment when the device will crash or most likely the S.O will force the closing of the application (crash) because the same is using an abusive amount of resources. Whenever possible give preference to use the widgets already present in Flutter to update your app, such as Stream Builder which will manage your stream, update the interface when necessary and automatically destroy the subscription when it is no longer needed.

  • Thank you so much for your attention! Concrete answer and that helped me a lot to understand why of the error!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.