下面代碼有三個button,內容都是一樣的,只不過包裝方式不同。
第一個是沒有包裝的,第二個用Builder包了一層,第三個封裝成了StatelessWidget。
運行一下,第一個button會報如下錯誤:
是說調用的Scaffod.of(context)找不到Scaffold。
import 'package:flutter/material.dart'; void main() => runApp(BuilderApp()); class BuilderApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: BuilderHomePage(), ); } } class BuilderHomePage extends StatefulWidget { @override _BuilderHomePageState createState() => _BuilderHomePageState(); } class _BuilderHomePageState extends State<BuilderHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Hello"), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ RaisedButton( onPressed: () { Scaffold.of(context).showSnackBar( new SnackBar(content: Text("Hello SnackBar1"))); }, child: Text("Test"), ), Builder( builder: (BuildContext context) { return RaisedButton( onPressed: () { Scaffold.of(context).showSnackBar( new SnackBar(content: Text("Hello SnackBar2"))); }, child: Text("Builder SnackBar"), ); }, ), WidgetTest() ], ), ), ); } } class WidgetTest extends StatelessWidget { @override Widget build(BuildContext context) { return Container( child: RaisedButton( onPressed: () { Scaffold.of(context).showSnackBar( new SnackBar(content: Text("Hello SnackBar3"))); }, child: Text("No Builder SnackBar"), ), ); } }
分析一下:
這是Scaffold.of(context)的源碼
可以看到這個方法返回的是findAncestorStateOfType()。其實所有.of(context).xxx這樣的方法都是調用這個東西。
點進去看看:
可以看到這個方法是在依次向上遍歷該widget的祖先,直到找到一個符合參數類型的祖先就退出。
注意最開始賦值是把當前widget的_parent賦給了ancestor,所以是從當前widget的父節點開始找的。
那么就很容易判斷了:
第一個button的context復用了build函數的context(android studio很貼心的會高亮兩個context的連接關系)
第二個button用Builder套了一層,它的context是Builder的builder函數的參數context
第三個button的context是StatelessWidget的build函數參數的context,就不截圖了。
由於第一個button的context和scaffold是同一個,所以從它的_parent往上找肯定找不到scaffold,所以報錯。
另外兩個button都是scaffold的子節點,他倆的_parent恰好就是scaffold,所以不會報錯。