1

I recognize FutureProvider can be used when a model will be given by a Future. It is needed to initialize the model by its init() async method, so I tried FutureProvider. However FutureProvider didn't give an instance of the model. It had given null.

Additionally while using ChangeNotifierProvider successfully updates UI, FutureProvider seems to not update UI when the notifyListeners() is called. Consumer gives same result. Is there anything to be fixed? Thank you.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class MyModel extends ChangeNotifier {
 int _point = 0;

 int get point => _point;

 set point(int value) {
   if (_point != value) {
     _point = value;
     notifyListeners();
   }
 }

 Future<void> init() async { /* Use await doSomething(); */ }
}

void main() => runApp(
  FutureProvider<MyModel>(
    create: (context) async {
      final model = MyModel();
      await model.init();
      return Future.value(model);
    },
    lazy: false,
    updateShouldNotify: (_, __) => true,
    child: MyHomePage(),
  ), 
);

class MyHomePage extends StatefulWidget {
  @override
 _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    final model = Provider.of<MyModel>(context);
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: Center(
          child: Text(
            '${model.point}',
            style: Theme.of(context).textTheme.display1,
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            model.point++;
          },
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}
0xCAF2
  • 193
  • 1
  • 11
  • not sure if this is what you're trying to achieve, but have a look at how I combined features of FutureProvider (waiting for async data) and ChangeNotifierProvider (change data and provide on request with notifyListeners()) https://stackoverflow.com/questions/72533330/how-to-combine-features-of-futureprovider-futurebuilder-waiting-for-async-data – Cedric Jun 07 '22 at 15:08

1 Answers1

0

You can use ChangeNotifierProvider. It will update your UI whenever notifyListeners is called.

ChangeNotifierProvider(
  create: (context) => MyModel()..init(), 
  child: MyHomePage(),
)

There is actually no need to call init if you are not doing anything inside your init method.

And if your MyModel class is only there for a single int value, you don't even need to use it. You can do something like:

ChangeNotifierProvider<ValueNotifier<int>>(
  create: (context) => ValueNotifier<int>(0),
  child: MyHomePage(),
);

And inside your HomePage

final counter = Provider.of<ValueNotifier<int>>(context);

You can use it inside your Text widget like:

Text('${counter.value}')
Selim Kundakçıoğlu
  • 1,986
  • 10
  • 20
  • OK, certainly `ChangeNotifierProvider` gives the model and updates UI properly. But I need to execute `await model.init();` while the sample don't include any real initialization. My question is why the sample code gives `null` to `Provider.of(context)`. `ChangeNotifierProvider` cannot be used in this case because Future must be provided. – 0xCAF2 Jan 28 '20 at 07:16
  • Since `FutureProvider` listens for a Future, it gives null(I guess). You are trying to avoid using `model.init()` is that correct? – Selim Kundakçıoğlu Jan 28 '20 at 07:26
  • No, `model.init()` must be executed in this case. – 0xCAF2 Jan 29 '20 at 05:37