chenenyu / lifecycle

Lifecycle support for Flutter widgets.
https://pub.dev/packages/lifecycle
Apache License 2.0
50 stars 6 forks source link

How to use with AutoRoute? #15

Closed AlexShniperson-INO closed 2 years ago

AlexShniperson-INO commented 2 years ago

Hi

When i try to use defaultLifecycleObserver with AutoRoute i got exception when navigate to other Route

======== Exception caught by widgets library =======================================================
The following assertion was thrown building WillPopScope(dependencies: [_ModalScopeStatus], state: _WillPopScopeState#d494e):
A GlobalKey was used multiple times inside one widget's child list.

The offending GlobalKey was: [LabeledGlobalKey<NavigatorState>#859d6]
The parent of the widgets with that key was: WillPopScope
  dependencies: [_ModalScopeStatus]
  state: _WillPopScopeState#d494e
The first child to get instantiated with that key became: Navigator-[LabeledGlobalKey<NavigatorState>#859d6]
  dirty
  state: NavigatorState#07176(lifecycle state: created)
The second child that was to be instantiated with that key was: WillPopScope
A GlobalKey can only be specified on one widget at a time in the widget tree.
The relevant error-causing widget was: 
  EmptyRouterPage EmptyRouterPage:file:///some_project/lib/route/app_router.gr.dart:31:46
When the exception was thrown, this was the stack: 
#0      Element._retakeInactiveElement.<anonymous closure> (package:flutter/src/widgets/framework.dart:3610:11)
#1      Element._retakeInactiveElement (package:flutter/src/widgets/framework.dart:3624:8)
#2      Element.inflateWidget (package:flutter/src/widgets/framework.dart:3655:33)
#3      Element.updateChild (package:flutter/src/widgets/framework.dart:3422:20)
#4      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16)
#5      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4840:11)
#6      Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
#7      StatefulElement.update (package:flutter/src/widgets/framework.dart:4872:5)
#8      Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
#9      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16)
#10     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4840:11)
#11     Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
#12     StatefulElement.update (package:flutter/src/widgets/framework.dart:4872:5)
#13     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
#14     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16)
#15     Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
#16     ProxyElement.update (package:flutter/src/widgets/framework.dart:5020:5)
#17     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
#18     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16)
#19     Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
#20     ProxyElement.update (package:flutter/src/widgets/framework.dart:5020:5)
#21     Element.updateChild (package:flutter/src/widgets/framework.dart:3412:15)
#22     ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4690:16)
#23     StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4840:11)
#24     Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
#25     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2620:33)
#26     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21)
#27     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:319:5)
#28     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1143:15)
#29     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1080:9)
#30     SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:863:7)
(elided 4 frames from class _RawReceivePortImpl, class _Timer, and dart:async-patch)
====================================================================================================

do you have any explanation how to fix that?

chenenyu commented 2 years ago

I think this is a covert bug in AutoRoute, lifecycle does't use any Key or WillPopScope in source code yet AutoRoute does it.

chenenyu commented 2 years ago

Check your code where AutoRoute initialized, or post it here and i'll try to analyze it. 😄

AlexShniperson-INO commented 2 years ago

here is example, try to navigate to DetailScreen by clicking Next page button https://github.com/AlexShniperson-INO/lifecycle-with-autoroute

chenenyu commented 2 years ago

Try to remove the key param _navigatorKey in here.

AlexShniperson-INO commented 2 years ago

it doesn't help, try to play with that project

chenenyu commented 2 years ago

If i use an instance of NavigatorObserver, it can trigger this issue.

class MainApp extends StatelessWidget {
  final _appRouter = AppRouter(_navigatorKey);

  final _observer = NavigatorObserver();

  MainApp({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: AutoRouterDelegate(
        _appRouter,
        navigatorObservers: () => [_observer],
      ),
      routeInformationParser: _appRouter.defaultRouteParser(),
    );
  }
}

But use a new instance every time is ok:

class MainApp extends StatelessWidget {
  final _appRouter = AppRouter(_navigatorKey);

  MainApp({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: AutoRouterDelegate(
        _appRouter,
        navigatorObservers: () => [NavigatorObserver()],
      ),
      routeInformationParser: _appRouter.defaultRouteParser(),
    );
  }
}

And replace it to LifecycleObserver() is fine too.

class MainApp extends StatelessWidget {
  final _appRouter = AppRouter(_navigatorKey);

  MainApp({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: AutoRouterDelegate(
        _appRouter,
        navigatorObservers: () => [LifecycleObserver()],
      ),
      routeInformationParser: _appRouter.defaultRouteParser(),
    );
  }
}

You can open an issue for AutoRoute. 😢

AlexShniperson-INO commented 2 years ago

hmm yes i see a new instance is working fine. this is apparently some kind of auto_route weirdness. thank you for help

chaturadilan commented 1 year ago

this works

class MainApp extends StatelessWidget {
  final _appRouter = AppRouter();
final _observer = LifecycleObserver();

  MainApp({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerDelegate: AutoRouterDelegate(
        _appRouter,
        navigatorObservers: () => [_observer],
      ),
      routeInformationParser: _appRouter.defaultRouteParser(),
    );
  }
}