1. 程式人生 > 其它 >Flutter中的資料共享-InheritedWidget

Flutter中的資料共享-InheritedWidget

技術標籤:flutter

文章目錄

一、前言

在Flutter中有時候我們要對資料進行共享,比如某個資料改變了,監聽該資料的UI也可以進行重新整理。官方提供了InheritedWidget元件來對此進行處理。以下通過定義一個元件點選按鈕使資料改變的功能來進行演示。

二、程式碼演示

SaveDataWidget.dart

首先定義一個繼承InheritedWidget抽象類的資料儲存類,程式碼如下:

//儲存資料的地方
class SaveDataWidget extends InheritedWidget{

  SaveDataWidget({
    @required this.data,
    Widget child
  }) :super(child: child);

  final int data; //需要在子樹中共享的資料,儲存點選次數

  //定義一個便捷方法,方便子樹中的widget獲取共享資料
  static SaveDataWidget of(BuildContext context) {
    // return context.dependOnInheritedWidgetOfExactType<ScopeData>();
    return context.getElementForInheritedWidgetOfExactType<SaveDataWidget>().widget;//可以阻止子元件的didChangeDependencies進行呼叫
  }

  //該回調決定當data發生變化時,是否通知子樹中依賴data的Widget
  @override
  bool updateShouldNotify(SaveDataWidget old) {
    //如果返回true,則子樹中依賴(build函式中有呼叫)本widget
    //的子widget的`state.didChangeDependencies`會被呼叫
    return old.data != data;
  }
}

資料顯示的UI,以下UI將按鈕點選事件與資料重新整理的進行分離,同時不使用setState(() {});進行UI重新整理,這樣也避免了資料耦合

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  int count = 0;

  @override
  Widget build(BuildContext context) {

    print('YM--------->父元件重新整理');
    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Material App Bar'),
        ),
        body: Center(
          child: SaveDataWidget(
            data: count,
            child: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.only(bottom: 20.0),
                  child: ChildWidget(),//子widget中依賴ShareDataWidget
                ),
                RaisedButton(
                  child: Text("Increment"),
                  //每點選一次,將count自增,然後重新build,ShareDataWidget的data將被更新
                  onPressed: () => setState(() => ++count),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

class ChildWidget extends StatefulWidget {
  @override
  _ChildWidgetState createState() => _ChildWidgetState();
}

class _ChildWidgetState extends State<ChildWidget> {
  @override
  Widget build(BuildContext context) {
    print('YM--------->子元件重新整理');
    //使用InheritedWidget中的共享資料
    return Text(SaveDataWidget
        .of(context)
        .data
        .toString());
  }
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    //父或祖先widget中的InheritedWidget改變(updateShouldNotify返回true)時會被呼叫。
    //如果build中沒有依賴InheritedWidget,則此回撥不會被呼叫。
    print("YM--------Dependencies change");
  }
}

三、參考連結:

  1. 資料共享(InheritedWidget):
    https://book.flutterchina.club/chapter7/inherited_widget.html
  2. InheritedWidget、InheritedModel的使用介紹:https://blog.csdn.net/vitaviva/article/details/105462686