contextって何?
contextをググると文脈、環境、状況などが出てきました。
contextは変数名なので、contextについて考えても理解が深まらないです。
contextはBuildContext型
です。
では、BuildContext型について話していきます。
BuildContext型って何?
ドキュメントを見ていく!
A handle to the location of a widget in the widget tree.
This class presents a set of methods that can be used from StatelessWidget.build methods and from methods on State objects.
Google翻訳
ウィジェット ツリー内のウィジェットの位置へのハンドル。
このクラスは、StatelessWidget.build メソッドおよび State オブジェクトのメソッドから使用できる一連のメソッドを提供します。
「ふむふむ、、、全くわかりません!」
できるだけわかりやすく説明していきます。
contextは先祖の情報を持ったクラス
と言えます。
widget自体は親のクラスにアクセスすることはできません。
だから、親クラスにアクセスしたい場合、contextを利用して親にアクセスすることになります。
contextが親のクラスを本当に持っているの?
それでは実際contextのメソッドを使って、親の情報を取得して行こう!
まずはコードを見ていきます。
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primaryColor: Colors.red),
home: Scaffold(
appBar: AppBar(),
body: Column(
children: <Widget>[
Theme(
data: ThemeData(primaryColor: Colors.green),
child: const WidgetA('green')),
Column(
children: <Widget>[
const WidgetA('red'),
Theme(
data: ThemeData(
primaryColor: Colors.blue,
),
child: const WidgetA('blue'),
)
],
)
],
),
));
}
}
class WidgetA extends StatelessWidget {
const WidgetA(this.text);
final String text;
@override
Widget build(BuildContext context) {
return Center(
child: SizedBox(
height: 100,
width: 200,
child: Card(
color: Theme.of(context).primaryColor,
child: Center(child: Text(text)),
),
),
);
}
}
今回は、赤色、青色、緑色のカードを表示するコードを書きました。
contextが出てきている箇所は2つあります。
1つ目はMyAppクラスの中のbuild関数の引数
2つ目も同様にWidgetAの中のbuild関数の引数になります。
1つ目の先祖を調べていきましょう。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(context.findAncestorWidgetOfExactType<MyApp>());
//省略
}
上記のようにfindAncestorWidgetOfExactType<調べたいクラス>()
で先祖のWidgetにアクセスできます。
結果はnull
でした。
何故でしょうか?
実は、contextは今いるクラスのより上のクラスしか探せません!
(以上じゃなくてより上なんです)
つまり、MyAppを探すには、MyAppの中のcontextじゃ探せないんです。
(MyAppより上にMyAppは存在しないからです。)
じゃあ、どうすればいいのか?
WidgetAのcontextを利用します。
MyAppとWidgetAは別々のクラスです。だから、WidgetAのcontextからMyAppクラスを探せるのは不思議に思えるかもしれません。これは、私も理解が不十分ですが、インスタンス化するとFlutter内で自動的にcontextが繋がるようになっているのだと思います。
WidgerA内のcontextで以下を実行します。
class WidgetA extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(context.findAncestorWidgetOfExactType<MyApp>());
//省略
}
MyApp
と出力されました.
ここで,context内には先祖の情報探せることを確認しました。
他にも色の情報を出力できたりします。
インスタンス化した地点より上の色を取得できるので,
green,red,blueの色が順番に出力されます
context.findAncestorWidgetOfExactType<Theme>().data.primaryColor;
contextはより詳しく理解するにはElementの知識が必要になります。
その内、詳しい記事も書いてみたいと考えてます