Flutter學習筆記(27)--數據共享(InheritedWidget)


如需轉載,請注明出處:Flutter學習筆記(27)--數據共享(InheritedWidget)

InheritedWidget是Flutter中非常重要的一個功能型組件,它提供了一種數據在widget樹中從上到下傳遞、共享的方式,比如我們在應用的根widget中通過InheritedWidget共享了一個數據,那么我們便可以在任意子widget中來獲取該共享的數據。

前言:假設有這么一個場景,A、B兩個組件,A組件有一個數據data,當A組件中的這個數據data發生變化后,B組件需要跟隨着做一些處理操作,這時候,如果不通過廣播或其他方式通知B組件,我們有什么辦法實現這個功能呢?

didChangeDependencies

在State對象中,有一個didChangeDependencies回調,這個回調會在“依賴”發生變化時被Flutter Framework調用。而這個“依賴”指的是子widget是否用到了父widget中的InheritedWidget共享數據。如果使用了,則代表子widget依賴InheritedWidget,反之如果沒有使用則代表沒有依賴。這種機制可以使子組件在所依賴的InheritedWidget發生變化時來更新自身。這也就可以實現我們前面所假設的場景了!

接下來先給大家看一下整體的代碼和效果截圖,心里先有一個大概的概念,帶着幾個概念去思考:1.依賴 2.didChangeDependencies回調 3.InheritedWidge通過什么來通知子widget 

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class FatherWidget extends InheritedWidget {
  final int data;

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

  //子樹通過該方法獲取共享數據
  static FatherWidget getData(BuildContext context) {
    return context.inheritFromWidgetOfExactType(FatherWidget);
  }

  //該回調決定當data發生變化時,是否通知子樹中依賴data的widget
  @override
  bool updateShouldNotify(FatherWidget oldWidget) {
    return oldWidget.data != data;
  }
}

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

class _ChildWidgetState extends State<ChildWidget> {
  @override
  Widget build(BuildContext context) {
    return new Text(FatherWidget.getData(context).data.toString());
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    //父或祖先widget中的InheritedWidget改變(updateShouldNotify返回true)時會被調用
    //如果build中沒有依賴InheritedWidget,則此回調不會被調用
    print("didChangeDependencies = " +
        FatherWidget.getData(context).data.toString());
  }
}

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'title',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('title'),
        ),
        body: new Center(
          child: FatherWidget(
            data: count,
            child: new Column(
              children: <Widget>[
                ChildWidget(),
                new FloatingActionButton(onPressed: _changeCount,child: new Icon(Icons.adjust),),
              ],
            ),
          ),
        ),
      ),
    );
  }

  _changeCount() {
    setState(() {
      ++count;
      print('mCount == ' + count.toString());
    });
  }
}

 整體代碼說明:

點擊按鈕后會調用_changeCount()方法,方法內給count數加1,然后通知框架重新build,重新build會給FatherWidget內的data重新賦值,data的數據發生了變化,updateShouldNotify會返回true,通知子widget執行didChangeDependencies回調來處理一下響應操作。

分塊說明一下實現數據共享都需要哪幾步:

1.用於存儲共享數據的父Widget,該widget繼承InheritedWidget

class FatherWidget extends InheritedWidget {
  final int data;

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

  //子樹通過該方法獲取共享數據
  static FatherWidget getData(BuildContext context) {
    return context.inheritFromWidgetOfExactType(FatherWidget);
  }

  //該回調決定當data發生變化時,是否通知子樹中依賴data的widget
  @override
  bool updateShouldNotify(FatherWidget oldWidget) {
    return oldWidget.data != data;
  }
}

2.子widget,用來處理依賴發生變化時的響應處理操作didChangeDependencies

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

class _ChildWidgetState extends State<ChildWidget> {
  @override
  Widget build(BuildContext context) {
    return new Text(FatherWidget.getData(context).data.toString());
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    //父或祖先widget中的InheritedWidget改變(updateShouldNotify返回true)時會被調用
    //如果build中沒有依賴InheritedWidget,則此回調不會被調用
    print("didChangeDependencies = " +
        FatherWidget.getData(context).data.toString());
  }
}

3.FahterWidget和ChildWidget產生依賴關系

  //子樹通過該方法獲取共享數據
  static FatherWidget getData(BuildContext context) {
    return context.inheritFromWidgetOfExactType(FatherWidget);
  }

 

4.數據更新,通過setState來重新build

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'title',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('title'),
        ),
        body: new Center(
          child: FatherWidget(
            data: count,
            child: new Column(
              children: <Widget>[
                ChildWidget(),
                new FloatingActionButton(onPressed: _changeCount,child: new Icon(Icons.adjust),),
              ],
            ),
          ),
        ),
      ),
    );
  }

  _changeCount() {
    setState(() {
      ++count;
      print('mCount == ' + count.toString());
    });
  }
}

 

最后需要注意一點,上面說到的依賴前提是兩個組件是父、子的關系,我試了一下,如果FatherWidget中沒有ChildWidget,只是單純的使用了FatherWidget的數據的話,是不會觸發didChangeDependencies回調的!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM