River_pod: The build method of ConsumerWidget is called 2 times

Created on 25 Sep 2020  Â·  10Comments  Â·  Source: rrousselGit/river_pod

Describe the bug
The build method of CounterText widget is called 2 times.

To Reproduce

class CounterText extends ConsumerWidget {
  @override
  Widget build(BuildContext context,
      T Function<T>(ProviderBase<Object, T> provider) watch) {
    final count = watch(counterState).state;
    print('update');
    return Text(count.toString());
  }
}

final counterState = StateProvider<int>((ref) => 0});

Expected behavior
The build method of CounterText widget should be called one time at start! (or I may not have understood something about how it works)

Thanks @rrousselGit for another great package

bug question

All 10 comments

@giandifra Hi. I would say you not have understood. It rebuild once on state changes from up to down.

class CounterText extends ConsumerWidget {
  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final count = watch(counterState).state;
    print('update'); // <= print once on rebuild.
    return Center(child: Text('$count')); // <= rebuild once at same time.
  }
}
 ```
`ConsumerWidget` is very useful and good alternative instead `StatefulWidget`. But if you provide multi providers to your `Widget` then I would recommend `Consumer` for better performance and put it deep as possible in your `Widget` tree.

```dart 
//  StatelessWidget....
// Here, rebuilds once only on first run to check the state.
return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          // This rebuilds only when firstCounterState changes
          Consumer(builder: (context, watch, child) {
            final count = watch(firstCounterState).state;
            print('rebuilding firstCounterState');
            return Center(child: Text('$count'));
          }),
          // This rebuilds only when secondCounterState changes
          Consumer(builder: (context, watch, child) {
            final count = watch(secondCounterState).state;
            print('rebuilding secondCounterState');
            return Center(child: Text('$count'));
          }),
        ],
      ),
    );
//....

final firstCounterState = StateProvider<int>((ref) => 0);
final secondCounterState = StateProvider<int>((ref) => 0);

@iamarnas I know this. I try to be more clear. This is full example.
Why print(update) is called 2 times at start?

void main() => runApp(ProviderScope(child: MyApp()));

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: CounterText(),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          context.read(counterState).state++;
        },
      ),
    );
  }
}

final counterState = StateProvider<int>((ref) => 0);

class CounterText extends ConsumerWidget {
  @override
  Widget build(BuildContext context,
      T Function<T>(ProviderBase<Object, T> provider) watch) {
    final count = watch(counterState).state;
    print('update');
    return Text(count.toString());
  }
}

@giandifra Strange. For me only once.

The first print(update); is called instantly, the second after 1 second more or less.

https://github.com/flutter/flutter/issues/52536#issuecomment-599127314

Flutter does not guarantee Widget.build will be called the minimum number of times possible. You should structure your application in a way that assumes build will be called on every frame - anything less is an optimization.

@giandifra Could you share your flutter version, the platform you are using and the steps to reproduce?

I cannot reproduce this issue.

Flutter 1.20.4 • channel stable • https://github.com/flutter/flutter.git
Framework • revision fba99f6cf9 (13 days ago) • 2020-09-14 15:32:52 -0700
Engine • revision d1bc06f032
Tools • Dart 2.9.2

What about the platform? Android? Web?

Ops, sorry... I tried on Android Emulator (Android 9) and Pixel 2XL (Android 10)... I saw just now that this behavior only occurs with "Hot Restart" and not in the first launch.

I've tested using the information you gave and still cannot reproduce the issue

But in any case, if this is happening only on hot-restart, it doesn't matter really matter. So I'll close this for now

Was this page helpful?
0 / 5 - 0 ratings