Boost」など、さまざまなカンファレンスを企画・運営しています。BOOKS(コードジン・ブックス)は、CodeZineの連載からカットアップした、開発現場の課題解決に役立つ書籍シリーズです。最後に参考資料BuildContextとはここまでのContextに関する理解があれば、BuildContextはFlutter、もしくはUIフレームワークに共通する特徴について理解すれば問題ないはずです。そこで、Flutterでの重要なContextであるBuildContextについて説明します。画面を構成するWidgetと定義としてのWidgetの関係Flutterでは各部品はすべてWidgetというクラスのインスタンスとして実行時に構築されますが、それらのWidgetを作成するためのコードは図3のように再利用されます。それらのコードからは実際のインスタンスを意識したコードが記述しにくくなっています。実際に画面上に表示されるWidgetの制御は表示上の最適化のために多くの部分でFlutterのフレーム側が制御しており、プログラマが想像している状況と異なる場合もあるからです。図3:画面でのWidgetインスタンスツリーとコードの関係図しかし、実際には画面表示だけではなく制御にかかわる部分では、このツリー構造やその場所を意識し制御する必要もあります。StatefulWidgetの場合には部品の状態とデータなどを保持するState情報なども管理しており、それらのデータや機能に他のWidgetからアクセスできる必要があります。そこで、Flutterでは図4のようにそれぞれの部品自体の情報を管理するBuildContextをもち、プログラマはBuildContextを通じて制御を行います。BuildContextはWidgetのbuildメソッド(リスト1)でアクセスできます。省略}(1)ではWidgetA1という名前でWidgetを定義しています。(2)では部品ツリー上のWidgetA1を識別するBuildContextが引数として渡されます。StatefulWidgetでもほぼ同様であり、Widgetを構築する前にそのWidgetを作成するためのBuildContextが用意されます。図4:Widgetでのbuildとインスタンスツリーの関係図ElementとはBuildContextの説明から少々離れますが、読者がReactやVueJSのような他のUIフレームワークを使ったことがあるのであれば、BuildContextの実装であるElementクラスを理解すると、これまでの経験から理解を助けることもできます。BuildContextの実装は、リスト2のようにElementクラスでもあります。省略}そして、このElementはWidgetライフサイクルを図5のように管理しています。図5:Elementが管理するWidgetのライフサイクルここで示すメソッドや役割などをみると、ReactやVueJSのようなものと似ていると感じる方もいると思います。他のUIフレームワークを使ったことがない読者の場合にはここまでの理解を思い出していただければ共通する部分があるので役立つはずです。BuildContextを引数にするofメソッドについてFlutterを利用していると、Navigator.ofのようなBuildContextを引数にとるofメソッドをたびたび見かけます。これらのメソッドが何をやっているかをもう少し詳しく見ていきます。先ほどのより汎用的なContextの図に当てはめてofメソッドを考えると、図6の各Contextで管理している各データやインスタンスの実体にアクセスするためのメソッドと理解することもできます。図6:抽象的なofメソッドの理解ofメソッドの仕組みBuildContextを引数にするofメソッドには、リスト3のようにいろいろあります。[リスト3]BuildContextの引数をとるofメソッドの一例MediaQuery.of(context)Navigator.of(context)ScaffoldMessenger.of(context)いずれのメソッドを使う場合でも、エラーなく動作している場合にはあまり意味を意識していなくても問題になることはありません。それぞれのofメソッドでやっていることは単純で、これまでのBuildContextのツリー構造がイメージできていれば理解は簡単です。これは図7のように自分自身のBuildContextから親からその親へと探索し、対象のStateオブジェクトが見つかるとそのオブジェクトを返します。図7:ofメソッドが探索する順番と制限このofメソッドで注意すべきなのは、引数で指定したBuildContextの親から探索するという点です。間違えたBuildContextを指定した場合には、リスト4のようなエラーが生じます。その場合には、この制限を思い出してもらえれば問題を解決できるはずです。Scaffold.利用したいBuildContextを用意するofメソッドを使いたいときに、引数として利用したいBuildContextがコード上存在しない場合があります。近くに存在するBuildContextを使えればよいと理解している方もいるかもしれません。リスト5のようなコードを実行した際には、必要なScaffoldのステート(ScaffoldState)が見つからず先ほどのようなエラーが生じます。))}(1)のコード自体には記述上の問題はありませんが、引数として利用しているcontextが正しくなくエラーが発生します。このコードの場合には、図8のような探索を行います。従って、このような場合にはScaffoldとIconButtonのWidgetの間に存在するBuildContextを作る必要があります。図8:問題となるofメソッドの利用例そのような場合に利用するのがBuilderウィジェットで、問題ないように変更したコードがリスト6です。))}(1)のbuilderプロパティの指定部分で、AppBarウィジェットとIconButtonウィジェットの間にBuildContextが存在するようにします。そのため、先ほどとコードは同じにもかかわらず(2)のコードは問題なく動作するようになります。この動作を先ほどと同じような図で示したのが、図9です。図9:Builderを使ったの利用例Builderウィジェットを使わなくても、必要なBuildContextをコード上に存在させたいだけなので、自分で定義したStatefulWidgetやStatelessWidgetではこのようなBuilderウィジェットは必要ありません。BuildContextを使いたいだけの場合が多いので、このようにBuilderウィジェットが多用されます。NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Technologies。執筆コミュニティ「WINGSプロジェクト」代表。NEW1DMM.comの施策から見る、事業をむしばむ「技術負債」への処方箋──リファクタリングの「言語化」でインシデントを予防2企業の7割超が「2025年の崖」を理解していないことが明らかに。NEW1DMM.comの施策から見る、事業をむしばむ「技術負債」への処方箋──リファクタリングの「言語化」でインシデントを予防2企業の7割超が「2025年の崖」を理解していないことが明らかに。NEW1DMM.comの施策から見る、事業をむしばむ「技術負債」への処方箋──リファクタリングの「言語化」でインシデントを予防2企業の7割超が「2025年の崖」を理解していないことが明らかに。12:00法務担当者、6割超が今後業務で「生成AIを使用したい」と回答。12:00オルツ、日本語RAGでは軽量型LLMとして世界最高の精度と推論速度を達成した「LHTM-OPT2」をリリース新着記事一覧を見るイベント今後の予定を見るCodeZineは、株式会社翔泳社が運営するソフトウェア開発者向けのWebメディアです。「デベロッパーの成長と課題解決に貢献するメディア」をコンセプトに、現場で役立つ最新情報を日々お届けします。イラストの無断転載を禁じます。記載されているロゴ、システム名、製品名は各社及び商標権者の登録商標あるいは商標です。