🌲

BuildContextとは何か?

2024/07/27に公開

👤対象者

  • BuildContextをただ書いてるだけの人。「はい。私もその一人です」
  • なんでこれを書かないと、Widgetをかけないのか知りたい人

What is BuildContext?

build()メソッドの中にある、BuildContextクラスとはなんなのか?

公式を翻訳すると

ウィジェット ツリー内のウィジェットの場所へのハンドル。

このクラスは、 StatelessWidget.buildメソッドおよびStateオブジェクトのメソッドから使​​用できる一連のメソッドを提供します 。

BuildContextオブジェクトは、 WidgetBuilder関数 ( StatelessWidget.buildなど )に渡され、 State.contextメンバーから利用できます。一部の静的関数 ( showDialog、Theme.ofなど) もビルド コンテキストを受け取り、呼び出し元のウィジェットに代わって動作したり、特定のコンテキスト専用のデータを取得したりすることができます。

各ウィジェットには独自のBuildContextがあり、これがStatelessWidget.buildまたはState.build関数によって返されるウィジェットの親になります。(同様に、 RenderObjectWidgetの子の親にもなります。)

特に、これはビルド メソッド内では、ビルド メソッドのウィジェットのビルド コンテキストが、そのビルド メソッドによって返されるウィジェットのビルド コンテキストと同じではないことを意味します。これにより、いくつかの厄介なケースが発生する可能性があります。たとえば、Theme.of(context) は、指定されたビルド コンテキストの最も近い包含Themeを検索します。ウィジェット Q のビルド メソッドが、返されたウィジェット ツリー内にTheme を含め、独自のコンテキストを渡すTheme.of を使用しようとすると、Q のビルド メソッドはそのThemeオブジェクトを見つけられません。代わりに、ウィジェット Q の祖先であったThemeが見つかります。返されたツリーのサブパートのビルド コンテキストが必要な場合は、Builder ウィジェットを使用できます。Builder.builder コールバックに渡されるビルド コンテキストは、Builder自体のビルド コンテキスト になります。

たとえば、次のスニペットでは、ビルド メソッド自体が作成するScaffoldウィジェットでScaffoldState.showBottomSheet メソッドが呼び出されます。Builderが使用されず、代わりに ビルド メソッド自体の引数が使用された場合、Scaffoldは見つからず、Scaffold.of関数は null を返します。context

動画を見た方がわかりやすいかも?

https://www.youtube.com/watch?v=rIaaH87z1-g

👨動画のおじさんによると...

Navigator.of(context), MediaQuery.of(context), itemBuilder:(context, index) {}さまざまなもので必要。なんなのか???

Widgetとは何だったのか???
他のWidgetとの関係の中で、自分の居場所をどう知るのか???
なんと知らない???

Widget Tree内の特定のインスタンスが存在する場所に関する情報を保存していない。

自分で、Widgetを作るときは、 StatelessWidget, StatefulWidgetを拡張して作る。内部実装を見ると、Flutter, Dartのコードが書いてあるが、一つだけ特別なものがある。

インスタンスを具体的にするcreateElementです。これらのエレメントが特定のWidgetの場所を追跡して、それにしたがい親と子の関係も追跡するオブジェクトです。と言っている。

ですから、新規WidgetをビルドするとFlutter FWは、そのWidgetを呼び出して、elementメソッドを作成します。

アプリの該当に必要な情報をランタイムで保持します。ランタイムっていうのは、「プログラムの実行時」。

その時点で、このエレメントは事実上他のエレメントツリー内のノードとなっています。node, ノードとは、node
木構造を読んだ方がいいかも

上から下に、木の垂れているものかな。グラフ理論の世界かも...

それぞれには、そのエレメントを示すウィジット参照があります。

「では、エレメントとは何ですか?
これは、単にBuildContextの一種です。」と動画で言っている。知らなかった💦

感想

BuildContextは、Widgetがどこにあるのか参照するためのもの。2019年のFlutter本によれば...

つまり、buid()メソッドの引数BuildContextクラスは、そのメソッドで返すウィジェット群のウィジェットツリー状の親のエレメントということです。

例えば、スーパークラスである StatelessWidget クラスのサブクラスの LoadingWidget クラスを作成していたら、build()メソッドのBuildContextクラスは、LoadingWidgetウィジェットのエレメントになります。このLoadingWidgetのエレメントとは、 StatelessWidgetが持っているStatelessElementということになります。

さっきの🌲の話を出すと、下のコードは、上から下にツリー状に垂れていくので、エレメントツリーの階層を取得することができます。

class LoadingWidget extends StatelessWidget {

  final bool isLoading;
  const LoadingWidget({super.key, required this.isLoading});

  
  Widget build(BuildContext context) {
    return isLoading
      ? const DecoratedBox(
        decoration: BoxDecoration(
          color: Color(0x44000000),
        ),
        child: Center(
          child: CircularProgressIndicator(),
        ),
      )
      : const SizedBox.shrink();
  }
}

上の方が親なら、下の方が子、子孫とか表現することになるようですね。上に戻れば先祖かな。先祖って昔の人だから...

おじいちゃん -> お父さん -> 子供
先祖 <- 子孫

せんぞ【先祖】

当家の現存の人が(家系の上で)出て来たもとになった人や人々。祖先。
・ 「―代々」
先代以前で既に生存者のいない代から前の人々。
・ 「―の中にそういう方もあったかも知れない」
その家の初代の主(あるじ)。始祖。
 「―以来の家宝」

しそん【子孫】

子や孫。まごこ。また、子、孫、その子、孫と(家系の上で)続く人々やそれに属する個人。

Discussion