開始介紹inheritedWidget
以前,先來介紹一個 知識點 爲後面的內容作鋪墊html
先介紹ancestorWidgetOfExactType
git
demo
地址: github.com/LZQL/flutte…github
能夠說是目前 全網 最完整的demo
演示了c#
返回給定類型的最近父widget
,該widget
的類型必須是具體widget
的子類。bash
通常來講,inheritFromWidgetOfExactType
更有用,由於繼承的widget
將在更改時觸發消費者從新構建。ancestorWidgetOfExactType
適用於交互事件處理程序(例如手勢回調)或執行一次性任務,例如斷言
您擁有或不具備做爲特定類型的父widget
。widget
的構建方法的返回值不該該依賴於該方法返回的值,由於若是該方法的返回值發生更改,構建上下文將不會從新生成
。這可能會致使生成方法中使用的數據發生更改,可是沒有從新生成widget
。微信
總結一下上面的意思:markdown
ancestorWidgetOfExactType
通常用於 斷言,是否有特定類型的父widget
ancestorWidgetOfExactType
能夠用來獲取父widget
的一些信息- 若是想要根據方法的返回值來判斷是否從新構建,
ancestorWidgetOfExactType
並不適用
下面會分別給出 上面的3
點總結來給出demo
場景app
這邊就不給出本身的demo
,直接看源碼,源碼的應用場景說明一切,這邊也是官方翻譯的最好證實less
Hero
的源碼,作了斷言,斷言就寫到這裏
widget
的一些信息WidgeC
是一個 加號按鈕, 點擊了WidgeC
,獲取HomepageState
調用incrementCounter
方法, , widgetA
,widgetB
,widgetC
會從新build
,看下圖ide
代碼位置 ancestor01.dart
/// ancestorWidgetOfExactType 獲取父widget的一些信息
class MyAncestorTree01 extends StatefulWidget {
@override
_MyAncestorTree01State createState() => _MyAncestorTree01State();
}
class _MyAncestorTree01State extends State<MyAncestorTree01> {
@override
Widget build(BuildContext context) {
return TopPage01();
}
}
class TopPage01 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Demo'),
),
body: HomePage(),
),
);
}
}
class HomePage extends StatefulWidget {
final HomePageState state = HomePageState();
@override
HomePageState createState() {
return state;
}
}
class HomePageState extends State<HomePage> {
int counter = 0;
void incrementCounter() {
setState(() {
counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
WidgetA(),
WidgetB(),
WidgetC(),
],
),
);
}
}
class WidgetA extends StatelessWidget {
@override
Widget build(BuildContext context) {
/// 獲取 HomePageState 來獲取 counter
final HomePage widget =
context.ancestorWidgetOfExactType(HomePage);
final HomePageState state = widget?.state;
return Center(
child: Text(
'${state == null ? 0 : state.counter}',
style: Theme.of(context).textTheme.display1,
),
);
}
}
class WidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text('Widget B Text');
}
}
class WidgetC extends StatelessWidget {
@override
Widget build(BuildContext context) {
/// 獲取 HomePageState 來 調用 加法操做
final HomePage widget = context.ancestorWidgetOfExactType(HomePage);
final HomePageState state = widget?.state;
return RaisedButton(
onPressed: () {
state?.incrementCounter();
},
child: Icon(Icons.add),
);
}
}
複製代碼
此demo
用來演示 子widget沒法檢測到父widget的更改
的具體狀況 爲後面的內容作鋪墊 我將ancestorWidgetOfExactType
封裝了一個 of 方法放到了TopPage02
裏面, 與 2. 獲取父widget 的一些信息
的使用場景不一樣。
注意看下圖,當我點擊了1 - AncestorWidgetOfExactType02 演示
按鈕,進入 demo
頁面,從右側能夠看出,由於是第一次進去,因此所有widget
都進行了build
操做,可是當我 點擊 了Add item
按鈕,TopPage02
會rebuild
可是WidgetA
, WidgetB
,WidgetC
,並不會進行rebuild
代碼位置ancestor02.dart
/// ancestorWidgetOfExactType
/// 子widget沒法檢測到父widget的更改
/// (父widget rebuild 子widget no rebuild)
class MyAncestorTree02 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new TopPage02(
child: new Scaffold(
appBar: new AppBar(
title: new Text('Title'),
),
body: new Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
new WidgetA(),
new WidgetB(),
new WidgetC(),
],
),
),
);
}
}
class Item {
String reference;
Item(this.reference);
}
class TopPage02 extends StatefulWidget {
TopPage02({
Key key,
this.child,
}) : super(key: key);
final Widget child;
final TopPage02State state = new TopPage02State();
@override
TopPage02State createState() {
return state;
}
static TopPage02State of(BuildContext context) {
/// 經過從 TopPage02 的 context 獲得樹結構來返回第一個 TopPage02State
return (context.ancestorWidgetOfExactType(TopPage02)
as TopPage02)
.state;
}
}
class TopPage02State extends State<TopPage02> {
List<Item> _items = <Item>[];
int get itemsCount => _items.length;
void addItem(String reference) {
setState(() {
_items.add(new Item(reference));
});
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}
class WidgetA extends StatefulWidget {
@override
_WidgetAState createState() => _WidgetAState();
}
class _WidgetAState extends State<WidgetA> {
@override
Widget build(BuildContext context) {
final TopPage02State state = TopPage02.of(context);
return new Center(
child: new RaisedButton(
child: new Text('WidgetA :Add Item'),
onPressed: () {
/// 這邊調用 addItem 方法,可是WidgetA,WidgetB,WidgetC
/// 並不會 build
/// 這就說明了:widget的構建方法的返回值不該該依賴於該方法返回的值,
/// 由於若是該方法的返回值發生更改,構建上下文將不會從新生成。
/// 這可能會致使生成方法中使用的數據發生更改,可是沒有從新生成widget
state.addItem('new item');
},
),
);
}
}
class WidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
final TopPage02State state = TopPage02.of(context);
return new Text('widgetB itemCount:${state.itemsCount}');
}
}
class WidgetC extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Text('I am Widget C');
}
}
複製代碼
特性:
InheritedWidget
是一個能夠在樹中高效地向下傳遞數據
的組件:咱們能夠在以InheritedWidget
爲節點的樹下任一Widget
中調用BuildContext.inheritFromWidgetOfExactType
來獲取離其最近的InheritedWidget
實例- 當以上面這種方式(調用
inheritFromWidgetOfExactType
方法時)被引用後,每當InheritedWidget
自身的狀態改變時,會致使「consumer」
(調用inheritFromWidgetOfExactType
方法的這個Child
) 從新build
第一點:在Flutter
中,正是經過InheritedWidget
來共享應用主題(Theme
)和Locale
(當前語言環境)信息的 第二點:解決了 上面提到ancestorWidgetOfExactType
的第三點不能經過返回值來進行從新build
的狀況
InheritedWidget
的在Widget
樹中數據傳遞方向是從上到下的,這和Notification
的傳遞方向正好相反。(後面系列文章介紹Notification
)
StatefulWidget
的State
對象有一個回調didChangeDependencies
,它會在「依賴」發生變化時被Flutter Framework
調用。而這個「依賴」指的就是是否使用了父widget
中InheritedWidget
的數據,若是使用了,則表明有依賴,若是沒有使用則表明沒有依賴。這種機制可使子組件在所依賴的主題、locale
等發生變化時有機會來作一些事情。
2 - InheritedWidget演示01
,發現問題這個例子 是參照 book.flutterchina.club/chapter7/in… 寫的同樣,相信不少人都看過
當我點擊了 click me
按鈕 加1,widgetA
,widgeB
,RaisedButton
會從新build
代碼位置:inheritedwidget01.dart
/// InheritedWidget01 , 會致使 `widgetA`,` widgeB`,`RaisedButton `會從新`build`
class InheritedWidgetTest01 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return InheritedWidgetTest01State();
}
}
class InheritedWidgetTest01State extends State<InheritedWidgetTest01> {
int tmpData = 0;
@override
Widget build(BuildContext context) {
print('InheritedWidgetTest01 build');
return Scaffold(
body: Center(
child: ShareInherited(
data: tmpData,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
WidgetA(),
WidgetB(),
RaisedButton(
child: Text("Click me"),
onPressed: () {
setState(() {
print('onPressed');
tmpData += 1;
});
},
),
],
),
),
),
);
}
}
class ShareInherited extends InheritedWidget {
final int data; //須要在子樹中共享的數據,保存點擊次數
ShareInherited({@required this.data, @required Widget child}) : super(child: child) {
print('ShareInherited construct');
}
/// 容許全部子 widget 經過包含的 context 得到最近的 ShareInherited 實例
/// 定義一個便捷方法,方便子樹中的widget獲取共享數據
/// 在內部,除了簡單地返回 ShareInherited 實例外,它還訂閱消費者 widget 以便用於通知更改
static ShareInherited of(BuildContext context) {
return context.inheritFromWidgetOfExactType(ShareInherited);
}
/// 用來告訴 InheritedWidget 若是對數據進行了修改,
/// 是否必須將通知傳遞給全部子 widget(已註冊/已訂閱)
@override
bool updateShouldNotify(ShareInherited oldWidget) {
// 若是返回true,則子樹中依賴(build函數中有調用)本widget
// 的子widget的`state.didChangeDependencies`會被調用
bool result = oldWidget.data != this.data;
print('ShareInherited updateShouldNotify result = $result');
return result;
}
}
class WidgetA extends StatefulWidget {
@override
_WidgetAState createState() => _WidgetAState();
}
class _WidgetAState extends State<WidgetA> {
@override
Widget build(BuildContext context) {
print('WidgetA build');
int data = ShareInherited.of(context).data;
return Text('WidgetA data = $data');
}
@override
void didChangeDependencies() {
print('WidgetA didChangeDependencies');
super.didChangeDependencies();
}
}
class WidgetB extends StatefulWidget {
@override
_WidgetBState createState() => _WidgetBState();
}
class _WidgetBState extends State<WidgetB> {
@override
Widget build(BuildContext context) {
print('WidgetB build');
return Text('WidgetB');
}
@override
void didChangeDependencies() {
print('WidgetB didChangeDependencies');
super.didChangeDependencies();
}
}
複製代碼
WidgetA
調用了inheritFromWidgetOfExactType
方法,得到了存放在 ShareInherited
對象裏的data
數據並顯示在WidgetA
內容上,同時使得 WidgetA
和ShareInherited
產生關聯;
當點擊 RaisedButton
觸發InheritedWidgetTest01
狀態更新時,InheritedWidgetTest01State
的 build
方法回調,從新構建 ShareInherited
對象傳入新值,因爲data
發生變化,ShareInherited
的方法updateShouldNotify
中返回了true
,最終使得與ShareInherited
關聯的WidgetA
觸發reBuild
。
當咱們運行並點擊RaisedButton
後,頁面表現得確實如上述所示,WidgetA
的內容由 WidgetA data = 0
變爲了WidgetA data = 1
,彷佛 InheritedWidget
正確的使用方式正是如此,可是log
裏輸出的倒是以下:
I/flutter (11303): onPressed
I/flutter (11303): InheritedWidgetTest01 build
I/flutter (11303): ShareInherited construct
I/flutter (11303): ShareInherited updateShouldNotify result = true
I/flutter (11303): WidgetA didChangeDependencies
I/flutter (11303): WidgetA build
I/flutter (11303): WidgetB build
複製代碼
能夠看到,結合前面的代碼邏輯分析,理論上只有 WidgetA
纔會reBuild
,而如今卻產生了I/flutter (11303): WidgetB build
這條記錄。這是爲何呢?
其實能夠從前面提到的特性2
找到答案。其中說到:InheriteWidget
狀態發生變化時會rebuild
相關的child
。 咱們知道,flutter
中Widget
被標識爲了@immutable
,便是不可變的,那麼所謂的狀態發生變化就意味着InheriteWidget
從新構建,因爲前面代碼中在InheriteWidget
構造時同時也構造的其child
對象,所以當InheriteWidget
從新構建時也會致使child
跟着從新構建,這樣也就失去了「rebuild相關的child」
的意義,
也就是說,要想特性2生效,須要保證
InheriteWidget
節點下的樹不會被從新構建。
將InheriteWidget
的child
轉化爲const
,這樣即便在重建 InheriteWidget
時,因爲其child
獲得的是同一個對象,也就不會致使這個子樹重建,選擇性reBuild
也就獲得了保證。可是因爲const
特性,相關的參數也必須是常量,所以須要重寫或修改的代碼量相對較多,所以更推薦解決方法2
的作法,這個方法在後面回寫
WidgeA
,WidgeB
,FlatButton
是處於同一級別的
從下圖能夠看到 當我點擊了click me
,widgetB
並不會被 rebuild
, 可是 WidgeA
和FlatButton
會rebuild
,這樣解決了WidgeB rebuild
的問題,可是 FlateButton
並不涉及到 頁面的數據刷新,若是我想要讓 FlatButton
也不rebuild
呢? 看const
的demo02
代碼位置:inheritedwidget_const_01.dart
/// 使用 const
/// Widget A ,FlatButton rebuild, Widget B no rebuild
class InheritedWidgetConst01 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return InheritedWidgetConst01State();
}
}
class InheritedWidgetConst01State extends State<InheritedWidgetConst01> {
int tmpData = 0;
@override
Widget build(BuildContext context) {
print('InheritedWidgetTest02 build');
return Scaffold(
body: Center(
child: ShareInherited(
data: tmpData,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const WidgetA(),
const WidgetB(),
FlatButton(
child: Text("Click me"),
onPressed: () {
setState(() {
print('onPressed');
tmpData += 1;
});
},
),
],
),
),
),
);
}
}
class ShareInherited extends InheritedWidget {
final int data;
ShareInherited({this.data, @required Widget child}) : super(child: child) {
print('ShareInherited construct');
}
@override
bool updateShouldNotify(ShareInherited oldWidget) {
bool result = oldWidget.data != this.data;
print('ShareInherited updateShouldNotify result = $result');
return result;
}
static ShareInherited of(BuildContext context) {
return context.inheritFromWidgetOfExactType(ShareInherited);
}
}
class WidgetA extends StatelessWidget {
const WidgetA();
@override
Widget build(BuildContext context) {
print('WidgetA build');
int data = ShareInherited.of(context).data;
return Text('WidgetA data = $data');
}
}
class WidgetB extends StatelessWidget {
const WidgetB();
@override
Widget build(BuildContext context) {
print('WidgetB build');
return Text('WidgetB');
}
}
複製代碼
你會發現,WidgeA
和 WidgeC
仍是rebuild
, 要解決這個問題,就須要用到 文章頂部提到的ancestorWidgetOfExactType
了,看 const demo 03,終極寫法
代碼位置 inheritedwidget_const_02.dart
/// 使用 const
/// Widget A ,Widget C rebuild, Widget B no rebuild
class InheritedWidgetConst02 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return InheritedWidgetConst02State();
}
}
class InheritedWidgetConst02State extends State<InheritedWidgetConst02> {
int tmpData = 0;
void addItem(){
setState(() {
tmpData++;
});
}
@override
Widget build(BuildContext context) {
print('InheritedWidgetTest02 build');
return Scaffold(
body: Center(
child: ShareInherited(
data: tmpData,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const WidgetA(),
const WidgetB(),
WidgetC(),
],
),
state: this,
),
),
);
}
}
class ShareInherited extends InheritedWidget {
final int data;
final InheritedWidgetConst02State state;
ShareInherited({this.data, @required Widget child,this.state}) : super(child: child) {
print('ShareInherited construct');
}
@override
bool updateShouldNotify(ShareInherited oldWidget) {
bool result = oldWidget.data != this.data;
print('ShareInherited updateShouldNotify result = $result');
return result;
}
static ShareInherited of(BuildContext context) {
return context.inheritFromWidgetOfExactType(ShareInherited);
}
}
class WidgetA extends StatelessWidget {
const WidgetA();
@override
Widget build(BuildContext context) {
print('WidgetA build');
int data = ShareInherited.of(context).data;
return Text('WidgetA data = $data');
}
}
class WidgetB extends StatelessWidget {
const WidgetB();
@override
Widget build(BuildContext context) {
print('WidgetB build');
return Text('WidgetB');
}
}
class WidgetC extends StatefulWidget {
@override
_WidgetCState createState() => _WidgetCState();
}
class _WidgetCState extends State<WidgetC> {
@override
Widget build(BuildContext context) {
print('Widge C build');
InheritedWidgetConst02State state = ShareInherited.of(context).state;
return FlatButton(
child: Text("Click me"),
onPressed: () {
setState(() {
print('onPressed');
state.addItem();
});
},
);
}
}
複製代碼
ShareInherited
的of
方法 ,增長了 是否 rebuild
的參數 你會發現 ,如今只有WidgeA
會rebuild
,完美啊
static ShareInherited of([BuildContext context, bool rebuild = true]) {
return (rebuild
? context.inheritFromWidgetOfExactType(ShareInherited)
: context.ancestorWidgetOfExactType(ShareInherited) );
}
複製代碼
代碼位置inheritedwidget_const_03.dart
/// 使用 const
/// Widget A rebuild, Widget B Widget C no rebuild
class InheritedWidgetConst03 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return InheritedWidgetConst03State();
}
}
class InheritedWidgetConst03State extends State<InheritedWidgetConst03> {
int tmpData = 0;
void addItem() {
setState(() {
tmpData++;
});
}
@override
Widget build(BuildContext context) {
print('InheritedWidgetTest02 build');
return Scaffold(
body: Center(
child: ShareInherited(
data: tmpData,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const WidgetA(),
const WidgetB(),
const WidgetC(),
],
),
state: this,
),
),
);
}
}
class ShareInherited extends InheritedWidget {
final int data;
final InheritedWidgetConst03State state;
ShareInherited({this.data, @required Widget child, this.state})
: super(child: child) {
print('ShareInherited construct');
}
@override
bool updateShouldNotify(ShareInherited oldWidget) {
bool result = oldWidget.data != this.data;
print('ShareInherited updateShouldNotify result = $result');
return result;
}
static ShareInherited of([BuildContext context, bool rebuild = true]) {
return (rebuild
? context.inheritFromWidgetOfExactType(ShareInherited)
: context.ancestorWidgetOfExactType(ShareInherited) );
}
}
class WidgetA extends StatelessWidget {
const WidgetA();
@override
Widget build(BuildContext context) {
print('WidgetA build');
int data = ShareInherited
.of(context)
.data;
return Text('WidgetA data = $data');
}
}
class WidgetB extends StatelessWidget {
const WidgetB();
@override
Widget build(BuildContext context) {
print('WidgetB build');
return Text('WidgetB');
}
}
class WidgetC extends StatelessWidget {
const WidgetC();
@override
Widget build(BuildContext context) {
print('Widge C build');
InheritedWidgetConst03State state = ShareInherited.of(context,false).state;
return FlatButton(
child: Text("Click me"),
onPressed: () {
print('onPressed');
state.addItem();
},
);
}
}
複製代碼
Child
對象到InheriteWidget
的Parent Widget
具體看代碼吧,稍顯複雜 ,這邊命名不是很規範,懶得改了, 太累了寫demo
,看代碼能夠知道
class ShareInherited extends StatelessWidget 複製代碼
這裏的ShareInherited
是一個 StatelessWidget
,也就是 上移了Child
對象到InheriteWidget
的Parent Widget
class _ShareInherited extends InheritedWidget 複製代碼
而_ShareInherited
纔是 具體的 InheritedWidget
看下圖可知 Widget A ,FlatButton rebuild, Widget B no rebuild
這時候咱們 同樣的 把 FlatButton
放到 WidgetC
而後上移到 InheriteWidget
的Parent Widget
看能不能實現讓 WidgeC
no rebuild
代碼位置inheritedwidget_out_01.dart
/// 上移`Child`對象到`InheriteWidget`的`Parent Widget`
/// Widget A ,FlatButton rebuild, Widget B no rebuild
class InheritedWidgetOut01 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return InheritedWidgetOut01State();
}
}
class InheritedWidgetOut01State extends State<InheritedWidgetOut01> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: MyWidget(
Column(
children: <Widget>[
WidgetA(),
WidgetB()
],
)
),
);
}
}
class MyWidget extends StatefulWidget {
final Widget child;
MyWidget(this.child);
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
int tempData = 0;
@override
Widget build(BuildContext context) {
return ShareInherited(
data: tempData,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
widget.child,
FlatButton(
child: Text("Click me"),
onPressed: () {
setState(() {
print('onPressed');
tempData += 1;
});
},
)
],
),
),
);
}
}
class ShareInherited extends StatelessWidget {
final int data;
final Widget child;
ShareInherited({
Key key,
this.data,
this.child
}): assert(child != null),
assert(data != null),
super(key: key);
static int of(BuildContext context) {
final _ShareInherited inheritedTheme = context.inheritFromWidgetOfExactType(_ShareInherited);
return inheritedTheme.shareInherited.data;
}
@override
Widget build(BuildContext context) {
return _ShareInherited(shareInherited:this , child: child,);
}
}
class _ShareInherited extends InheritedWidget{
final ShareInherited shareInherited;
_ShareInherited({
Key key,
@required this.shareInherited,
@required Widget child,
}):assert(shareInherited != null),
super(key: key, child: child);
@override
bool updateShouldNotify(_ShareInherited oldWidget) {
return shareInherited.data != oldWidget.shareInherited.data;
}
}
class WidgetA extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('WidgetA build');
int data = ShareInherited.of(context);
return Text('WidgetA data = $data');
}
}
class WidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('WidgetB build');
return Text('WidgetB');
}
}
複製代碼
你會發現 Widget A ,Widget C rebuild, Widget B no rebuild
若是想要 讓 Widge C no rebuild,看out demo 03
代碼位置inheritedwidget_out_02.dart
/// 上移`Child`對象到`InheriteWidget`的`Parent Widget`
/// Widget A ,Widget C rebuild, Widget B no rebuild
class InheritedWidgetOut02 extends StatefulWidget {
@override
_InheritedWidgetOut02State createState() => new _InheritedWidgetOut02State();
}
class _InheritedWidgetOut02State extends State<InheritedWidgetOut02> {
@override
Widget build(BuildContext context) {
return new MyInheritedWidget(
child: new Scaffold(
appBar: new AppBar(
title: new Text('Title'),
),
body: Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[new WidgetA(), new WidgetB(), new WidgetC()],
),
),
),
);
}
}
class MyInheritedWidget extends StatefulWidget {
MyInheritedWidget({
Key key,
this.child,
}) : super(key: key);
final Widget child;
@override
MyInheritedWidgetState createState() => new MyInheritedWidgetState();
static MyInheritedWidgetState of([BuildContext context]) {
return (context.inheritFromWidgetOfExactType(_MyInherited) as _MyInherited).data;
// 經過從 MyInheritedWidget 的 context 獲得樹結構來返回第一個 MyInheritedWidgetState
}
}
class MyInheritedWidgetState extends State<MyInheritedWidget> {
int tempData = 0;
/// Helper method to add an Item
void addItem() {
setState(() {
tempData++;
});
}
@override
Widget build(BuildContext context) {
return new _MyInherited(
data: this,
child: widget.child,
);
}
}
class _MyInherited extends InheritedWidget {
_MyInherited({
Key key,
@required Widget child,
@required this.data,
}) : super(key: key, child: child);
final MyInheritedWidgetState data;
@override
bool updateShouldNotify(_MyInherited oldWidget) {
return true;
}
}
class WidgetA extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('Widget A build');
final MyInheritedWidgetState state = MyInheritedWidget.of(context);
return Text('WidgetA data = ${state.tempData}');
}
}
class WidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('Widget B build');
return Text('WidgetB');
}
}
class WidgetC extends StatefulWidget {
@override
_WidgetCState createState() => _WidgetCState();
}
class _WidgetCState extends State<WidgetC> {
@override
Widget build(BuildContext context) {
print('Widget C build');
final MyInheritedWidgetState state = MyInheritedWidget.of(context);
return RaisedButton(
child: Text("Click me"),
onPressed: () {
print('onPressed');
state.addItem();
},
);
}
}
複製代碼
由於這個demo
的 Perfomance
界面展現不夠形象,就直接展現輸出log
查看結果比較形象
能夠發現 Widget A rebuild, Widget B Widget C no rebuild ,完美啊 ,寫到這裏已經要吐了
代碼位置inheritedwidget_out_03.dart
/// 上移`Child`對象到`InheriteWidget`的`Parent Widget`
/// Widget A rebuild, Widget B Widget C no rebuild
class InheritedWidgetOut03 extends StatefulWidget {
@override
_InheritedWidgetOut03State createState() => new _InheritedWidgetOut03State();
}
class _InheritedWidgetOut03State extends State<InheritedWidgetOut03> {
@override
Widget build(BuildContext context) {
return new MyInheritedWidget(
child: new Scaffold(
appBar: new AppBar(
title: new Text('Title'),
),
body: Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[new WidgetA(), new WidgetB(), new WidgetC()],
),
),
),
);
}
}
class MyInheritedWidget extends StatefulWidget {
MyInheritedWidget({
Key key,
this.child,
}) : super(key: key);
final Widget child;
@override
MyInheritedWidgetState createState() => new MyInheritedWidgetState();
static MyInheritedWidgetState of(
[BuildContext context, bool rebuild = true]) {
return (rebuild
? context.inheritFromWidgetOfExactType(_MyInherited) as _MyInherited
: context.ancestorWidgetOfExactType(_MyInherited) as _MyInherited)
.data;
// 經過從 MyInheritedWidget 的 context 獲得樹結構來返回第一個 MyInheritedWidgetState
}
}
class MyInheritedWidgetState extends State<MyInheritedWidget> {
int tempData = 0;
/// Helper method to add an Item
void addItem() {
setState(() {
tempData++;
});
}
@override
Widget build(BuildContext context) {
return new _MyInherited(
data: this,
child: widget.child,
);
}
}
class _MyInherited extends InheritedWidget {
_MyInherited({
Key key,
@required Widget child,
@required this.data,
}) : super(key: key, child: child);
final MyInheritedWidgetState data;
@override
bool updateShouldNotify(_MyInherited oldWidget) {
return true;
}
}
class WidgetA extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('Widget A build');
final MyInheritedWidgetState state = MyInheritedWidget.of(context);
return Text('WidgetA data = ${state.tempData}');
}
}
class WidgetB extends StatelessWidget {
@override
Widget build(BuildContext context) {
print('Widget B build');
return Text('WidgetB');
}
}
class WidgetC extends StatefulWidget {
@override
_WidgetCState createState() => _WidgetCState();
}
class _WidgetCState extends State<WidgetC> {
@override
Widget build(BuildContext context) {
print('Widget C build');
final MyInheritedWidgetState state = MyInheritedWidget.of(context, false);
return RaisedButton(
child: Text("Click me"),
onPressed: () {
print('onPressed');
state.addItem();
},
);
}
}
複製代碼
方法1 : 能夠查看TickerMode
這個類
方法2: 能夠查看 Theme
類
book.flutterchina.club/chapter7/in…