Skip to content

[compass_app] UI state never updates for the HomeScreen (regression after the implementation of #2788) #2877

Description

@Maxalkin

Serious bug, application doesn't work the inteded way.

(Flutter 3.44.8; platform: Windows; tested on commit 978919b)

Steps to reproduce:

  1. Book a new trip;
  2. Come back to a home screen;
  3. You can't see new trip, unless you hot reload.

Before moving initialization of HomeViewModel into HomeScreenContainer, it relied on rebuild that go_router did:

  1. User moves to the home route '/' or deeper;
  2. All previous routes including the one where user moved are getting rebuilt, which results in creating new instances of viewModels, which results in them calling _load and fetching latest data from repository.

Now it seems that HomeViewModel is just initialized once in HomeScreenContainer and never updates.


Generally according to this statement, the current way go_router "manages" ui states, is wrong, which already was unfolded in issue#2574, but outside of users sharing their ways on how to avoid this behavior, it never really recieved much attention.

So maybe a solution to this bug will also lead to a solution for issue#2574?

I myself temporarly solved issue#2574 in a way where viewModel only updates when user moves directly to a route it was going to. Hopefully this helps:

class RouteLifecycleListener extends StatefulWidget {
  const RouteLifecycleListener({
    required this.onResume,
    required this.child,
    super.key,
  });
  final VoidCallback onResume;
  final Widget child;

  @override
  State<RouteLifecycleListener> createState() => _RouteLifecycleListenerState();
}

class _RouteLifecycleListenerState extends State<RouteLifecycleListener>
    with RouteAware {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context)! as PageRoute);
  }

  @override
  void didPopNext() {
    widget.onResume();
  }

  @override
  void dispose() {
    routeObserver.unsubscribe(this);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return widget.child;
  }
}
...
    GoRoute(
      path: '/home',
      name: AppRoute.home.name,
      builder: (context, state) => Provider(
        create: (context) {
          return HomeViewModel(
            ...
          );
        },
        builder: (context, _) {
          return RouteLifecycleListener(
            onResume: () => context.read<HomeViewModel>().load.execute(),
            child: HomeScreen(viewModel: context.read()),
          );
        },
      ),
      routes: [ ...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions