从MediaQuery看InheritedWidget的用法

  • 继承InheriedWidget
class MediaQuery extends InheritedWidget {
  • 包含一个需要共享的变量,这里为data
    !! 坑点来了

这里必须还有一个child字段,必传,但这还不是最关键的, 最关键的是super也需要把这个字段带上

哪些widget需要共享数据,就放到child下面

 const MediaQuery({
    Key key,
    @required this.data,
    @required Widget child,
  }) : assert(child != null),
       assert(data != null),
       super(key: key, child: child);

final MediaQueryData data;
  • 实现updateShouldNotify方法,一般是比较该变量是否相同,不同则更新
 @override
  bool updateShouldNotify(MediaQuery oldWidget) => data != oldWidget.data;
  • 实现一个静态的of方法,用来获取这个共享变量,传入的参数固定为context,方法体中固定使用 context.inheritFromWidgetOfExactType(xxx);的方式获取xxx
    这个xxx即我们实现的继承自InheritedWidget的子类,这里是MediaQuery
 static MediaQueryData of(BuildContext context, { bool nullOk = false }) {
    assert(context != null);
    assert(nullOk != null);
    final MediaQuery query = context.inheritFromWidgetOfExactType(MediaQuery);
    if (query != null)
      return query.data;
    if (nullOk)
      return null;
    throw FlutterError(
      'MediaQuery.of() called with a context that does not contain a MediaQuery.\n'
      'No MediaQuery ancestor could be found starting from the context that was passed '
      'to MediaQuery.of(). This can happen because you do not have a WidgetsApp or '
      'MaterialApp widget (those widgets introduce a MediaQuery), or it can happen '
      'if the context you use comes from a widget above those widgets.\n'
      'The context used was:\n'
      '  $context'
    );
  }

贴一个示例代码:

import 'package:flutter/material.dart';
import 'package:flutter_ui_common/constants.dart';

class InheriedWidgetTester extends StatefulWidget {
  @override
  _InheriedWidgetTesterState createState() => _InheriedWidgetTesterState();
}

class _InheriedWidgetTesterState extends State {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    var testModel = TestModel(age: 1);
    var scaffold = new Scaffold(
        appBar: AppBar(title: Text("test inheriedwidget")),
        body: Column(
          children: [InheriedWidgetA(), InheriedWidgetB()],
        ),
      );
    var testModelQuery = _TestModelQuery(
      data: testModel,
      child: scaffold,
    );
    return testModelQuery;
  }
}

class InheriedWidgetA extends StatefulWidget {
  @override
  _InheriedWidgetAState createState() => _InheriedWidgetAState();
}

var data = "显示修改的age";
class _InheriedWidgetAState extends State {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: MediaQuery.of(context).size.width,
      height: 80,
      color: white,
      child: RaisedButton(
          child: Text(
            data,
            style: TextStyle(color: black, fontSize: 15),
          ),
          onPressed: () {
            int age = _TestModelQuery.of(context).age;
            print('修改 的age'+age.toString());
            setState(() {
              data = age.toString();
            });
          }),
    );
  }
}

class InheriedWidgetB extends StatefulWidget {
  @override
  _InheriedWidgetBState createState() => _InheriedWidgetBState();
}

class _InheriedWidgetBState extends State {
  @override
  Widget build(BuildContext context) {
    return Container(
      width: MediaQuery.of(context).size.width,
      height: 80,
      color: white,
      child: RaisedButton(
          child: Text(
            "修改age为9",
            style: TextStyle(color: black, fontSize: 15),
          ),
          onPressed: () {
            var testModel = _TestModelQuery.of(context);
            testModel.age = 9;
          }),
    );
  }
}

class TestModel {
   TestModel({this.age});

  var age;
}

class _TestModelQuery extends InheritedWidget {
  const _TestModelQuery({Key key, this.data, Widget child}) : super(key: key, child: child);
  final TestModel data;

  /// 获取共享数据
  static TestModel of(BuildContext context) {
    _TestModelQuery query =
        context.inheritFromWidgetOfExactType(_TestModelQuery);
    return query.data;
  }

  @override
  bool updateShouldNotify(_TestModelQuery oldWidget) =>
      data.age != oldWidget.data.age;
}

github

你可能感兴趣的:(从MediaQuery看InheritedWidget的用法)