Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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();
}
like image 952
FlutterFirebase Avatar asked Oct 26 '19 10:10

FlutterFirebase


1 Answers

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"),
        ),
      ),
    );
  }

}
like image 112
JunYao Yuan Avatar answered Sep 30 '22 17:09

JunYao Yuan