gskinnerTeam / flutter-routed-widget-switcher

Declaratively switch child widgets based on the current `Router` location.

Home Page:https://pub.dev/packages/routed_widget_switcher

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Refactoring

PlugFox opened this issue · comments

Using scheduleMiscrotask in initState is a very very very bad idea!

Instead of
https://github.com/gskinnerTeam/flutter-routed-widget-switcher/blob/master/lib/routed_widget_switcher.dart#L41-L46
you may:

@override
void didChangeDependencies() {
  delegate ??= Router.of(context).routerDelegate..addListener(_handleRouteChanged);
  provider ??= Router.of(context).routeInformationProvider..addListener(_handleRouteChanged);
  super.didChangeDependencies();
}

But anyway, is a bad idea to do what you do that way

Just use AnimatedBuilder, like that:

class YourWidget extends StatelessWidget {
   @override
   Widget build(_) => AnimatedBuilder(
      animation: Listenable.merge(<Listenable>[
        Router.of(context).routerDelegate,
        Router.of(context).routeInformationProvider,
      ]),
      builder: ...
   );
}
commented

Thanks for the idea, it lgtm and that merge code is really neat, I didn't know you could do that.

But why is initState + scheduleMicrotask a bad idea? I've never heard this before.

commented

This is done:

Leaving open as I'm still curious what was so bad about the initial implementation ( other than it being a waste of code :D )

You are welcome C:

mount -> initState -> didChangeDependencies -> build is synchronuos operations and not planning in Event Loop.
scheduleMicrotask is async operation, planning some activity in Event Loop queue, after previous Microtasks and before any Events (usually Futures, but this is very simplistically because Event Loop is another abstraction).

Any future (except SynchronyousFuture) or scheduleMicrotask changed widget state is a bad idea in initState, didChangeDependencies. didUpdateWidget, build and etc.

It's disrespectful flutter build a one-way synchronous pipeline where initState fully eval initial state before didChangeDependencies.
didChangeDependencies fully eval state before build.

When you plan microtask for event loop in init state, your variables are null in the first build.

Also, you can use addPostFrameCallback for planning some activity after frame painting, but also, if you are not changing widget state and in except situations.

commented

I've always considered addPostFrameCallback and scheduleMicrotask pretty much interchangeable.

I'm not sure I agree it's as bad as you think, (I don't really see practical ways this can hurt you) but certainly your suggestion is better in this case!