欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Flutter学习笔记(27)--数据共享(InheritedWidget)

程序员文章站 2022-05-23 11:05:17
InheritedWidget是Flutter中非常重要的一个功能型组件,它提供了一种数据在widget树中从上到下传递、共享的方式,比如我们在应用的根widget中通过InheritedWidget共享了一个数据,那么我们便可以在任意子widget中来获取该共享的数据。 ......

如需转载,请注明出处: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());
    });
  }
}

Flutter学习笔记(27)--数据共享(InheritedWidget)

 整体代码说明:

点击按钮后会调用_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回调的!!!