abstractclassElementextendsDiagnosticableTreeimplementsBuildContext{ /// Creates an element that uses the given widget as its configuration. /// /// Typically called by an override of [Widget.createElement]. Element(Widget widget) : assert(widget != null), _widget = widget;
Element _parent; ... Map<Type, InheritedElement> _inheritedWidgets;
void notifyClients(InheritedWidget oldWidget) { if (!widget.updateShouldNotify(oldWidget)) return; assert(_debugCheckOwnerBuildTargetExists('notifyClients')); for (Element dependent in _dependents) { assert(() { // check that it really is our descendant Element ancestor = dependent._parent; while (ancestor != this && ancestor != null) ancestor = ancestor._parent; return ancestor == this; }()); // check that it really depends on us assert(dependent._dependencies.contains(this)); dependent.didChangeDependencies(); } }
if (widget == null) { throw ScopedModelError(); } else { return (widget as _InheritedModel<T>).model; } }
staticType _type<T>() => T;
到这里, 就可以发现它和inherient做法相同了, 首先获取到InheritedWidget的类型, _type<_InheritedModel<T>>()得到_InheritedModel<T>, 然后判断是否需要在改变的时候重绘, 默认是True, 如果需要重绘就会调用inheritFromWidgetOfExactType去建立依赖, 如果为false, 则会调用ancestorInheritedElementForWidgetOfExactType, 这个方法不会建立依赖, 所以在改变的时候不会收到通知并重绘, 官方的注释有这么一句: This method does not establish a relationship with the target in the way that [inheritFromWidgetOfExactType] does.
@override Widget build(BuildContext context) { // At the top level of our app, we'll, create a ScopedModel Widget. This // will provide the CounterModel to all children in the app that request it // using a ScopedModelDescendant. return ScopedModel<CounterModel>( model: model, child: MaterialApp( title: 'Scoped Model Demo', home: CounterHome('Scoped Model Demo'), ), ); } }
// Start by creating a class that has a counter and a method to increment it. // // Note: It must extend from Model. classCounterModelextendsModel{ int _counter = 0;
intget counter => _counter;
void increment() { // First, increment the counter _counter++;
// Then notify all the listeners. notifyListeners(); } }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(title), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('You have pushed the button this many times:'), // Create a ScopedModelDescendant. This widget will get the // CounterModel from the nearest parent ScopedModel<CounterModel>. // It will hand that CounterModel to our builder method, and // rebuild any time the CounterModel changes (i.e. after we // `notifyListeners` in the Model). ScopedModelDescendant<CounterModel>( builder: (context, child, model) { return Text( model.counter.toString(), style: Theme.of(context).textTheme.display1, ); }, ), ], ), ), // Use the ScopedModelDescendant again in order to use the increment // method from the CounterModel floatingActionButton: ScopedModelDescendant<CounterModel>( builder: (context, child, model) { return FloatingActionButton( onPressed: model.increment, tooltip: 'Increment', child: Icon(Icons.add), ); }, ), ); } }
Comments