MOB-LOG

モブおじの記録 (Programming, 統計・機械学習)

FlutterでWidget遷移したいがBuildContextが参照できないとき→ GlobalKey<State>をnavigatorKeyに指定してアプリのどこからでも参照できるようにする

TL;DR

Flutterにて、Navigator.of(context)としてウィジェットを遷移するために、いつでもどこでも参照できる最新のBuildContextを保持した変数が欲しかった。

MaterialAppnavigatorKeyはどこからでも参照できる様子なので、main()runAppするとき、大本となるMaterialAppnavigatorKeyGlobalKey<NavigatorState>を渡してnavigatorKey.currentState!から最新のBuildContextを参照する。

いきさつ

ログイン情報を監視するために FirebaseAuth.instance.authStateChanges().listen()で状態の変化を監視して、ログインしてなかった場合ログインウィジェットへ遷移させようとしていた。ただしログインページへ遷移するためにNavigator.of(context)とする必要があるのでBuildContextが必要になる。Listenerに最新の画面遷移をさせるためには、最新のBuildContextを与えたいので、最新のBuildContextが毎度毎度更新される何かしらのクラスのインスタンスを渡す必要があるな、となった。

MaterialAppnavigatorKeyというメンバがあるらしく、こいつにGlobalKey<State>インスタンスを与えておけば、navigatorKey.currentState! としていつでもどこでもアプリのWidigetのスコープ内であれば最新のBuildContextが取得できるんだとか (Globalに宣言するから←多分重要)。

GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigatorKey,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My App'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // グローバルキーを使用してWidget遷移
            navigatorKey.currentState!.push(MaterialPageRoute(
              builder: (context) => SecondPage(),
            ));
          },
          child: Text('Go to Second Page'),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Page'),
      ),
      body: Center(
        child: Text('This is the second page.'),
      ),
    );
  }
}