InheritedWidget混乱

问题描述 投票:2回答:1

颤振documentation for InheritedWidget

基类小工具,有效地传播下来的树信息。

为了获得从>构建上下文插件继承特定类型的最近的实例,使用BuildContext.inheritFromWidgetOfExactType。

继承的窗口小部件,以这种方式引用时,会导致消费者重建时继承的部件本身的变化状态。

鉴于在颤振部件是不可变的,并且在该示例代码..

class FrogColor extends InheritedWidget {
  const FrogColor({
    Key key,
    @required this.color,
    @required Widget child,
  }) : assert(color != null),
       assert(child != null),
       super(key: key, child: child);

  final Color color;

  static FrogColor of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(FrogColor);
  }

  @override
  bool updateShouldNotify(FrogColor old) => color != old.color;
}

颜色属性是final所以不能被重新分配。假设这个小部件正好处于树的顶部,因为在大多数例子中,当将这个不断是有用的。对于要更换小部件,一个新的实例将被创建。

据推测,这里做到这一点,无论是通过为孩子也将被创建,引起孩子的后代也重建,创造了其childresn等新情况的新实例..

结束了反正重建整个树。因此,通过使用inheritFromWidgetOfExactType应用的选择性更新是没有意义的,当InheritedWidget实例的数据,该实例永远不会改变?

编辑:

这是什么,我不知道我可以放在一起简单的例子。在这个例子中,只有这样才能“变化”,这是靠近应用程序的根是有它的父(InheritedWidget/FrogColor)的MyApp重建。这将导致它重建其子女创造FrogColor的新实例,并且被传递一个新的子实例。我没有看到任何其他方式的InheritedWidget/FrogColor将改变其状态,如文档中

......将导致消费者重建时继承的部件本身的变化状态。

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

void main() {

  runApp(MyApp());
}

class FrogColor extends InheritedWidget {
  const FrogColor({
    Key key,
    @required this.color,
    @required Widget child,
  }) : assert(color != null),
        assert(child != null),
        super(key: key, child: child);

  final Color color;

  static FrogColor of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(FrogColor);
  }

  @override
  bool updateShouldNotify(FrogColor old) => color != old.color;
}

class MyApp extends StatefulWidget {
  // This widget is the root of your application.

  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp>
{
  @override
  Widget build(BuildContext context) {
    var random = Random(DateTime.now().millisecondsSinceEpoch);

    return FrogColor(
        color : Color.fromARGB(255,random.nextInt(255),random.nextInt(255),random.nextInt(255)),
        child:MaterialApp(
            title: 'Flutter Demo',
            home: Column (
                children: <Widget>[
                  WidgetA(),
                  Widget1(),
                  FlatButton(
                      child:Text("set state",style:TextStyle(color:Colors.white)),
                      onPressed:() => this.setState((){})
                  )
                ]
            )
        )
    );
  }
}

class WidgetA extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("Ran Build ${this.runtimeType.toString()}");
    return  WidgetB();
  }
}
class WidgetB extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("Ran Build ${this.runtimeType.toString()}");
    return  Text("SomeText",style:TextStyle(color:FrogColor.of(context).color));
  }
}
class Widget1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("Ran Build ${this.runtimeType.toString()}");
    return  Widget2();
  }
}
class Widget2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print("Ran Build ${this.runtimeType.toString()}");
    return  Text("SomeText",style:TextStyle(color:FrogColor.of(context).color));
  }
}

此外,这样做的输出是

I/flutter (24881): Ran Build WidgetA
I/flutter (24881): Ran Build WidgetB
I/flutter (24881): Ran Build Widget1
I/flutter (24881): Ran Build Widget2

因此,所有的子控件总是重建。制作在inheritFromWidgetOfExactType毫无意义也做登记。

Aaditi:

为了应对在评论@RémiRousselet答案,修改上面的例子,像

class MyAppState extends State<MyApp>
{
  Widget child;

  MyAppState()
  {
    child = MaterialApp(
        title: 'Flutter Demo',
        home: Column (
            children: <Widget>[
              WidgetA(),
              Widget1(),
              FlatButton(
                  child:Text("set state",style:TextStyle(color:Colors.white)),
                  onPressed:() => this.setState((){})
              )
            ]
        )
    );
  }

  @override
  Widget build(BuildContext context) {
    var random = Random(DateTime.now().millisecondsSinceEpoch);
    return FrogColor(
        color : Color.fromARGB(255,random.nextInt(255),random.nextInt(255),random.nextInt(255)),
        child: child
    );
  }
}

通过存储应使同一子树传递给每个重建InhertedWidget不能构建功能之外修改树的作品。这不只是工作,导致已经与inheritFromWidgetOfExactType注册得到重建部件的重建,而不是其他。

虽然@RémiRousselet说,这是不正确的子树存储为国家,我不认为有任何理由,这是不正常的一部分,INFACT他们这样做在一些谷歌的视频教程。 Here她创造和保持为状态的一部分子树。在她的情况下,2 StatelessColorfulTile()部件。

dart flutter inherited-widget
1个回答
0
投票

据推测,这里做到这一点,无论是通过作为一个孩子也将被创建,引起孩子的后代也重建,造就了其子女等的新实例的新实例..

结束了反正重建整个树。

这就是你的困惑来自

一个widget重建不会强迫其后代重建。

当父重建,框架内部检查newChild == oldChild,在这种情况下,孩子是不是重建。

因此,如果一个小部件的情况下并没有改变,或者如果它覆盖operator==则有可能在其父被更新的窗口小部件不重建。

这也是为什么AnimatedBuilder提供child性质的原因之一:

AnimatedBuilder(
  animation: animation,
  builder: (context, child) {
    return Container(child: child,);
  },
  child: Text('Hello world'),
);

这确保了当为动画的整个持续时间,child被保留,因此不重建。导致更优化的UI。

© www.soinside.com 2019 - 2024. All rights reserved.