Flutter的InheritedWidget

2020-04-11  本文已影响0人  Harely

  官方说的一通看了以后有点不太了解,通过把代码敲了一通,然后打断点跑了一遍终于知道是咋回事了。
  开发做多了,完全跟iOS的设计模式单例差不多在存储数据方面。但是在单例上又加了通知全局刷新整个app组件,相当简单暴力。
好了,先看第一个代码Demo:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class ShareDataWidget extends InheritedWidget {

  ///需要在子树中共享的数据,保存点击次数
  final int data;

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

  ///定义一个便捷方法,方便子树中的widget获取共享数据 
  static ShareDataWidget of(BuildContext context) {
    //return context.inheritFromWidgetOfExactType(ShareDataWidget);// 废弃了
    return context.dependOnInheritedWidgetOfExactType(aspect: ShareDataWidget);
  }

  ///该回调决定当data发生变化时,是否通知子树中依赖data的Widget
  @override
  bool updateShouldNotify(ShareDataWidget oldWidget) {
    // TODO: implement updateShouldNotify
    // 如果返回true,则子树中依赖(build函数中有调用)本widget
    // 的子widget的`state.didChangeDependencies`会被调用
    return oldWidget.data != data;
  }
  
}


/*
  * 实现一个子组件_TestWidget,在其build方法中引用ShareDataWidget中的数据。
  * 同时,在其didChangeDependencies() 回调中打印日志
*/
class  _TestWidget extends StatefulWidget {
  @override
  _TestWidgetState createState() => new _TestWidgetState();
  
}

class  _TestWidgetState extends State<_TestWidget> {
  
  @override
  Widget build(BuildContext context) {
    print("共享数据: ${ShareDataWidget.of(context).data.toString()}");
    //使用InheritedWidget中的共享数据,也就产生了依赖
    return Text(
      "依赖产生:" + ShareDataWidget.of(context)
                      .data
                      .toString()
                      
    );
  }


@override
  void didChangeDependencies() {
    // TODO: implement didChangeDependencies
    super.didChangeDependencies();
    //父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。
    //如果build中没有依赖InheritedWidget,则此回调不会被调用。
    print("Dependencies change【依赖发生了改变】");
  }
  
}



class  InheritedWidgetTestRoute extends StatefulWidget {

  @override
  _InheritedWidgetTestRouteState createState() => new _InheritedWidgetTestRouteState();
  
}

class  _InheritedWidgetTestRouteState extends State<InheritedWidgetTestRoute> {

  int count = 0;

  @override
  Widget build(BuildContext context) {

    return Center(
      child: ShareDataWidget(
        data: count,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children:<Widget>[
            Padding(padding: const EdgeInsets.only(bottom: 20.0),
            child: _TestWidget(),// 子widget中依赖ShareDataWidget
            ),
            RaisedButton(
              ////每点击一次,将count自增,然后重新build,ShareDataWidget的data将被更新
              onPressed: () => setState(() => ++count),
              child: Text("Increment"),
              )
          ]
        ),
        ),
    );
  }
}

调用

void main() {
  runApp(MyApp());
  // runApp(Text("hellosjglajgl"));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home:Scaffold(
        appBar: AppBar(
          title: Text('Hello Flutter'),
        ),
        body: InheritedWidgetTestRoute(),
      )
    );
  }
  
}

运行效果:


依赖刷新

  感觉这个可以做app的用户信息展示,感觉很棒。

  一般来说,子widget很少会重写didChangeDependencies()方法,因为在依赖改变后framework也都会调用build()方法。但是,如果你需要在依赖改变后执行一些昂贵的操作,比如网络请求,这时最好的方式就是在didChangeDependencies()方法中执行,这样可以避免每次build()都执行这些昂贵操作。

上一篇下一篇

猜你喜欢

热点阅读