FlutterFirebase
FlutterFirebase

Reputation: 2343

ChangeNotifier mounted equivalent?

I am extract some logic from Stateful Widget to Provider with ChangeNotifier: class Model extends ChangeNotifier {...}

In my Stateful Widget I have:

if (mounted) {
  setState(() {});
}

How I can check if Widget is mounted in Model?

For example how I can call:

if (mounted) {
  notifyListeners();
}

Upvotes: 7

Views: 2995

Answers (4)

nashihu
nashihu

Reputation: 849

you can just override notifyListeners like this

class Model extends ChangeNotifier { 

    @override
    void notifyListeners() {
        WidgetsBinding.instance.addPostFrameCallback((t) {
            print("skip notify after ${t.inMilliseconds}ms");
            super.notifyListeners();
        });

    }

}

no need additional variables / constructor modification

Upvotes: 0

Aryan Bahmani
Aryan Bahmani

Reputation: 21

Just use a custom ChangeNotifier class.

import 'package:flutter/cupertino.dart';

class CustomChangeNotifier extends ChangeNotifier {
  bool isDisposed = false;

  @override
  void notifyListeners() {
    if (!isDisposed) {
      super.notifyListeners();
    }
  }

  @override
  void dispose() {
    isDisposed = true;
    super.dispose();
  }
}

Upvotes: 0

zero.one
zero.one

Reputation: 1553

as long as you wrap your widget with the provider model state and as it is known once your widget is disposed the provider model that is wrapping it already get disposed by default

so all you have to do is to define a variable isDisposed and modify the notifyListeners as below

MyState with ChangeNotifier{

// to indicate whether the state provider is disposed or not
 bool _isDisposed = false;


   // use the notifyListeners as below
   customNotifyListeners(){
    if(!_isDisposed){
       notifyListeners()
    }
   }




 @override
  void dispose() {
    super.dispose();
    _isDisposed = true;
  }

}

Upvotes: 0

JunYao Yuan
JunYao Yuan

Reputation: 243

A simple way is pass 'State' of your Stateful Widget as a parameter to your 'Model'.

Like this:

class Model extends ChangeNotifier {

  Model(this.yourState);

  YourState yourState;

  bool get _isMounted => yourState.mounted;
}

class YourState extends State<YourStatefulWidget> {
  Model model;

  @override
  void initState() {
    super.initState();
    model = Model(this);
  }

  @override
  Widget build(BuildContext context) {
    // your code..
  }
}

I think you don't need to check the State is mounted or not. You just need to check the Model has been already disposed. You can override dispose() method in ChangeNotifier:

class Model extends ChangeNotifier {
  bool _isDisposed = false;

  void run() async {
    await Future.delayed(Duration(seconds: 10));
    if (!_isDisposed) {
      notifyListeners();
    }  
  }

  @override
  void dispose() {
    super.dispose();
    _isDisposed = true;
  }
}

And don't forget dispose Model when the State is disposed:

class YourState extends State {
  Model model;

  @override
  void initState() {
    super.initState();
    model = Model();
  }

  @override
  void dispose() {
    model?.dispose();
    super.dispose();
  }
  /// Your build code...

}

Or you can use ChangeNotifierProvider in package Provider, it will help you to dispose Model automatically.

class YourState extends State {
  Model model;

  @override
  void initState() {
    super.initState();
    model = Model();
  }

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<Model>(
      builder: (build) => model,
      child: Container(
        child: Consumer<Model>(
          builder: (context, model, widget) => Text("$model"),
        ),
      ),
    );
  }

}

Upvotes: 8

Related Questions