HELLO大神們,小弟初學Flutter有個問題:
在view的檔案裡因為有 Widget build(BuildContext context)
所以能很方便的取得context來使用,但小弟現在想要在一個外部的class直接取用context故採用此navigatorKey.currentContext以便在任何位置取用context,不果我發現似乎這樣取得的context和 Widget build
附帶的context有點不同,根據print出來的東西判斷:
從一個statefull class呼叫的context:_myClassName(dependencies: [MediaQuery], state: _myClassName#b89b3)
從navigatorKey.currentContext叫出來的context:Navigator-[LabeledGlobalKey<NavigatorState>#4bbf2](dependencies: [HeroControllerScope, UnmanagedRestorationScope], state: NavigatorState#3c029(tickers: tracking 1 ticker))
從print的結構即可看出這應該是不同的context,我認為是這部分導致了我無法正確取用這個功能(code如下):
(如果把'NavigationService.navigatorKey.currentContext' 換成來自 Widget build
的context就成順利運作)
FlutterToastr.show(
'MSG: King of flevor',
NavigationService.navigatorKey.currentContext,
duration: FlutterToastr.lengthLong,
position: FlutterToastr.bottom,
backgroundRadius: 32
);
請問有人知道如何解決此問題嗎? (使用環境: flutter stable 3.0.5)
其實只要追蹤一下你使用的FlutterToastr
套件就可以得知問題所在。
原始碼54行中,作者利用context
取得OverlayState
。
overlayState = Overlay.of(context, rootOverlay: rootNavigator ?? false);
繼續檢查Overlay
後會發現實際上是由Navigator
所創建。
而Navigator
往上就是WidgetsApp
及MaterialApp
。
能看出階層關係是:MaterialApp > WidgetsApp > Navigator > Overlay
接下來檢查關鍵的Overlay.of
中是如何靠context
取得OverlayState
。
可以看到原始碼中是使用findRootAncestorStateOfType
或findAncestorStateOfType
。
final OverlayState? result = rootOverlay
? context.findRootAncestorStateOfType<OverlayState>()
: context.findAncestorStateOfType<OverlayState>();
至此就能發現問題所在,原因在於findRootAncestorStateOfType
及findAncestorStateOfType
實際上都是依照context在樹中的位置往上搜尋。
所以navigatorKey.currentContext
所得到的context
階層在Navigator
,往上搜尋只有WidgetsApp
及MaterialApp
,導致套件中使用Overlay.of
無法取得OverlayState
。
建議除了使用Navigator
外,盡量不要直接使用navigatorKey.currentContext
。
而是配合架構改用當下顯示Widget
的context
。
如真的堅持要任何地方都可以用到的context的話,可以考慮在你的MainPage使用GlobalKey
。