Bloc: flutter_infinite_list bug with MaterialPageRoute

Created on 10 Feb 2019  ·  19Comments  ·  Source: felangel/bloc

Describe the bug
There's a bug with MaterialPageRoute that makes the build method called every time.

If we have no posts, we could not be able to reftech them, because in the second time hasReachedMax wil be true.

This is not a flutter_bloc bug, but i though it was good to warm.

these issues can add information:

flutter/flutter#14124
theyakka/fluro/i#57

To Reproduce
Steps to reproduce the behavior:

In my case, I have a Form with TextFormFields and when I tap them, build method is called again.
I'm use using Fluro to handle routes, but that happens anyway.

Expected behavior

This was not supposed to happen.

Screenshots
bug_flutter

Doctor

[√] Flutter (Channel stable, v1.0.0, on Microsoft Windows [versão 10.0.17134.523], locale pt-BR)
    • Flutter version 1.0.0 at C:\flutter
    • Framework revision 5391447fae (2 months ago), 2018-11-29 19:41:26 -0800
    • Engine revision 7375a0f414
    • Dart version 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297)

[√] Android toolchain - develop for Android devices (Android SDK 28.0.3)
    • Android SDK at C:\Android\Sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-28, build-tools 28.0.3
    • ANDROID_HOME = C:\Android\Sdk
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)
    • All Android licenses accepted.

[√] Android Studio (version 3.3)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 32.0.1
    • Dart plugin version 182.5124
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1248-b01)

[√] VS Code (version 1.30.2)
    • VS Code at C:\Users\1513 MX7\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 2.22.3

[√] VS Code, 64-bit edition (version 1.31.0)
    • VS Code at C:\Program Files\Microsoft VS Code
    • Flutter extension version 2.22.3

[√] Connected device (1 available)
    • Moto Z2 Play • 0041301651 • android-arm • Android 8.0.0 (API 26)

• No issues found!

Additional context
Add any other context about the problem here.

question

Most helpful comment

In general, I would not mix blocs with navigation/routing because blocs should only deal with business logic and navigation is presentation logic. In addition, you lose the ability to reuse your blocs across AngularDart and Flutter if the bloc is tightly coupled with the navigation.

Again, I'm not very familiar with Fluro, but I suspect that before when you were dispatching from the route handler, that code was being called on every widget build (which can happen when you change focus in TextFormField etc...) and as a result you were dispatching the fetch over and over again and overwriting your current state. By moving the fetch dispatch into the initState of the StatefulWidget we are making sure that even across lots of rebuilds, the widget doesn't keep dispatching the fetch event and instead only dispatches it on the initial load.

Does that help?

All 19 comments

Thanks for reporting this however I don’t think it’s a flutter bug because we should build widgets so that they can be rebuilt every frame. Can you share your code and I can help you find a solution?

Yes! My repo has a branch that i'm refactoring it using BLoC.

Awesome! I’ll take a look in the next few hours and might open a PR if that okay?

You're welcome ! Thank you !
My app is in Portuguese, but it has a demo gif explaing it.

@alefcarlos so I started to take a look and I'm unsure how to reproduce the case where you have no posts. Can you please tell me the steps to reproduce? Thanks!

@felangel , in my case it's Collections.

in collections/collections_services:

  Future<List<Collection>> fetch(int startIndex, int limit) async {
    await Future.delayed(Duration(seconds: 1));
    // final response = await httpClient.get(
    //     '${Application.apiUri}/collections?_start=$startIndex&_limit=$limit');

    // if (response.statusCode != 200)
    //   throw 'Não foi possível recuperar as coleções, tente novamente.';
    print(startIndex);
    print(limit);
    return Application.collections.skip(startIndex).take(limit).toList();
    // final data = json.decode(response.body) as List;
    // return data.map((item) => Collection.fromMap(item)).toList();
  }

Application.collections is List<Collection>

I'm not using web api for now, so it all in memory.

When you open the app the list is empty, so you need to create a new Collection tapping the fab button in home. And when you save the last inserted one will not be in the list.

@alefcarlos I have created a new Collection and see the 4 items and am not sure what to do after that. Can you send me a video of steps to reproduce the problem? Sorry but I don't understand Portuguese 😝

Of course !

You must be in the bloc_pattern branch.

bug_flutter

In the fancy_fab.dart i have this code below:

```dart
Widget addCollection() {
return Container(
child: FloatingActionButton(
heroTag: 'addCollection',
onPressed: () {
animate();
Application.router
.navigateTo(context, CollectionsRoute.createCollectionRoute)
.then((createdId) {
if (createdId != null) {
widget.collectionsBloc.dispatch(CollectionsFetchEvent());

          showSnackBar(
            context,
            'Coleção criada com sucesso',
            action: SnackBarAction(
              label: 'Ver coleção',
              onPressed: () => Application.router
                  .navigateTo(context, '/collection/$createdId'),
            ),
          );
        }
      });
    },
    tooltip: 'Adicionar coleção',
    child: Icon(Icons.add),
  ),
);

}```

After creating I dispatch the event again.

I put more logs:

bug_flutter

You can see, every time i taped the text:

  1. CollectionsFetchEvent from collectionsHandler
  2. mapEventToState Instance of 'CollectionsFetchEvent'

That seems like it could be an issue with Fluro and I'm not very familiar with it to be honest but give me a few more mins to see if I can figure out how to fix that.

If you look this issue and this , you will se the same problem. Even without Fluro.

Take a look at https://github.com/alefcarlos/colecao_bolso_app/pull/2/files.

I just moved the dispatch out of the router and into the StatefulWidget

It seems like the only problem now is you don't update hasReachedMax in your bloc so you always show the bottom loader.

I got it, I will refactor the others. But i did not understand why.

What part did you not understand?

I just moved the dispatch out of the router and into the StatefulWidget.

Why this is working now ?

In general, I would not mix blocs with navigation/routing because blocs should only deal with business logic and navigation is presentation logic. In addition, you lose the ability to reuse your blocs across AngularDart and Flutter if the bloc is tightly coupled with the navigation.

Again, I'm not very familiar with Fluro, but I suspect that before when you were dispatching from the route handler, that code was being called on every widget build (which can happen when you change focus in TextFormField etc...) and as a result you were dispatching the fetch over and over again and overwriting your current state. By moving the fetch dispatch into the initState of the StatefulWidget we are making sure that even across lots of rebuilds, the widget doesn't keep dispatching the fetch event and instead only dispatches it on the initial load.

Does that help?

Helps a lot hahahaha

Thank you very much !

Sorry to bother you.

No problem! Happy to help 👍

If you have any other questions, don't hesitate to ask!

Not sure if you checked out the gitter but for random questions/discussions you can post there and I'm generally pretty good about responding quickly.

Thanks!

Was this page helpful?
0 / 5 - 0 ratings