iT邦幫忙

0

Flutter中BuildContext的差別

  • 分享至 

  • xImage

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)

我曾經把contxt 傳入到新的頁面做使用沒問題
你可能檢查一下你的key是否是在正確的位置
return MaterialApp(
navigatorKey: NavigationService.navigatorKey, // set property
)
金牌鴨 iT邦新手 5 級 ‧ 2022-09-01 09:26:53 檢舉
關於正確取值這點我有發現,我把這個global key context丟給flutter內建的AlertDialog是可以正常運作的,但就是傳給flutterToastr會報錯,所以我猜應該和問題提到的兩個之間的差別有關。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

1
jordandes
iT邦新手 5 級 ‧ 2022-09-23 11:32:33

其實只要追蹤一下你使用的FlutterToastr套件就可以得知問題所在。

原始碼54行中,作者利用context取得OverlayState

overlayState = Overlay.of(context, rootOverlay: rootNavigator ?? false);

繼續檢查Overlay後會發現實際上是由Navigator所創建。
Navigator往上就是WidgetsAppMaterialApp
能看出階層關係是:
MaterialApp > WidgetsApp > Navigator > Overlay

接下來檢查關鍵的Overlay.of中是如何靠context取得OverlayState
可以看到原始碼中是使用findRootAncestorStateOfTypefindAncestorStateOfType

    final OverlayState? result = rootOverlay
        ? context.findRootAncestorStateOfType<OverlayState>()
        : context.findAncestorStateOfType<OverlayState>();

至此就能發現問題所在,原因在於findRootAncestorStateOfTypefindAncestorStateOfType實際上都是依照context在樹中的位置往上搜尋。

所以navigatorKey.currentContext所得到的context階層在Navigator,往上搜尋只有WidgetsAppMaterialApp,導致套件中使用Overlay.of無法取得OverlayState

建議除了使用Navigator外,盡量不要直接使用navigatorKey.currentContext
而是配合架構改用當下顯示Widgetcontext

如真的堅持要任何地方都可以用到的context的話,可以考慮在你的MainPage使用GlobalKey

我要發表回答

立即登入回答