flutterflutter-webflutter-state

dispose() is called when using AutomaticKeepAliveClientMixin


I am under the impression that using AutomaticKeepAliveClientMixin would prevent the states dispose() callback from being called when the Widget isn't visible anymore.

However, I have a situation where dispose() and initState() get called every time I hide/show a Widget, even though I implemented AutomaticKeepAliveClientMixin correctly.

class IdleScreenState extends State<IdleScreen> with AutomaticKeepAliveClientMixin {

  @override
  void initState() {
    super.initState();
    print('IdleScreen initState');
  }


  @override
  void dispose() {
    print('IdleScreen dispose');
    super.dispose();
  }


  @override
  Widget build(BuildContext context) {
    super.build(context);

    // ...build the page...
  }

  @override
  bool get wantKeepAlive => true;

}

This is how I hide/show this Widget

class MainScreen extends State<MainScreen> with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    super.build(context);

    return somecondition ? IdleScreen() : OtherScreen();
  }

  @override
  bool get wantKeepAlive => true;

}

Every time this Widget (screen) is shown, initState()gets called, and every time I hide it, dispose() gets called. It's as if the AutomaticKeepAliveClientMixin has no effect. All other similar issues I could find seem to be due to either missing the wantKeepAlive => true or the super.build(context), but they are 100% there in the code.

I tried supplying a GlobalKey for IdleScreen as well, but that didn't have any effect.

However, if I use an IndexedStack or Offstage to hide/show the widget, it works as expected (initState() and dispose() don't get called when hiding/showing the widget).

  IndexedStack(
    index: somecondition ? 0 : 1,
    children: [
      IdleScreen(),
      OtherScreen()
    ],
  ),

Maybe I'm mistaken, but isn't the whole purpose of AutomaticKeepAliveClientMixin to not have to manually keep the widget around using this technique?

This is in a web project, if that matters.


Solution

  • AutomaticKeepAliveClientMixin doesn't prevent state disposal if you remove your widget from the tree. It prevents garbage collection, if you have all your widgets in the tree and some of them are off-screen. The good example is tabs which are children of TabView or PageView.

    IndexedStack already preserves its children (it's a built-in behaviour), so you don't have to add AutomaticKeepAliveClientMixin to each of them.