当前位置:网站首页>Shutter: about inheritedwidget
Shutter: about inheritedwidget
2022-07-03 12:01:00 【J_ D_ Chi】
Write it at the front
InheritedWidget Is a component for data sharing , Its data transmission direction is from top to bottom , So when we put data in it , When there is data change , Those who depend on it Widget Data changes can be obtained .
Content
abstract class InheritedWidget extends ProxyWidget {
const InheritedWidget({ Key? key, required Widget child })
: super(key: key, child: child);
@override
InheritedElement createElement() => InheritedElement(this);
@protected
bool updateShouldNotify(covariant InheritedWidget oldWidget);
}
updateShouldNotify() Method is used to make Framework Judge whether to remind those who depend on this InheritedWidget Of Widget.
InheritedWidget Is an abstract class , It means that we must realize it , Here we use 《Flutter actual combat 》 Examples in a book 7.2 Data sharing (InheritedWidget) As an expression of :
class ShareDataWidget extends InheritedWidget {
ShareDataWidget({
@required this.data,
Widget child
}) :super(child: child);
final int data; // Data that needs to be shared in the subtree , Save hits
// Define a convenient method , In convenience subtree widget Get shared data
static ShareDataWidget of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
}
// The callback determines when data When something changes , Whether to notify dependency in subtree data Of Widget
@override
bool updateShouldNotify(ShareDataWidget old) {
// If you return true, Dependency in subtree (build Call in function ) Ben widget
// The son of widget Of `state.didChangeDependencies` Will be called
return old.data != data;
}
}
class _TestWidget extends StatefulWidget {
@override
__TestWidgetState createState() => new __TestWidgetState();
}
class __TestWidgetState extends State<_TestWidget> {
@override
Widget build(BuildContext context) {
// Use InheritedWidget Shared data in
return Text(ShareDataWidget
.of(context)
.data
.toString());
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
// Father or ancestor widget Medium InheritedWidget change (updateShouldNotify return true) Will be called .
// If build No dependency in InheritedWidget, Then this callback will not be called .
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( // Use ShareDataWidget
data: count,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: _TestWidget(),// Son widget The dependence ShareDataWidget
),
RaisedButton(
child: Text("Increment"),
// Every click , take count Self increasing , And then again build,ShareDataWidget Of data Will be updated
onPressed: () => setState(() => ++count),
)
],
),
),
);
}
}
When we click the button , And then call setState() Methods , When the next frame comes , Will call InheritedWidgetTestRoute Conduct rebuild, Then call it recursively child Of update() Method .
By inheritance :
Will call first ProxyElement Of update() Method , It's called in updated() Method :
abstract class ProxyElement extends ComponentElement {
@override
void update(ProxyWidget newWidget) {
final ProxyWidget oldWidget = widget;
assert(widget != null);
assert(widget != newWidget);
super.update(newWidget);
assert(widget == newWidget);
updated(oldWidget);
_dirty = true;
rebuild();
}
@protected
void updated(covariant ProxyWidget oldWidget) {
notifyClients(oldWidget);
}
}
InheritedElement Rewrote updated() Method , Here we use our updateShouldNotify() Method , You can know that the whole process is to traverse a Map Type of _dependents, Rely on the inside Element Call their didChangeDependencies Method .
class InheritedElement extends ProxyElement {
final Map<Element, Object?> _dependents = HashMap<Element, Object?>();
...
@override
void updated(InheritedWidget oldWidget) {
if (widget.updateShouldNotify(oldWidget))
super.updated(oldWidget);
}
@override
void notifyClients(InheritedWidget oldWidget) {
...
for (final Element dependent in _dependents.keys) {
...
notifyDependent(oldWidget, dependent);
}
}
...
@protected
void notifyDependent(covariant InheritedWidget oldWidget, Element dependent) {
dependent.didChangeDependencies();
}
}
So where do you add these dependencies ?
abstract class Element extends DiagnosticableTree implements BuildContext {
...
@override
T? dependOnInheritedWidgetOfExactType<T extends InheritedWidget>({Object? aspect}) {
...
final InheritedElement? ancestor = _inheritedWidgets == null ? null : _inheritedWidgets![T];
if (ancestor != null) {
return dependOnInheritedElement(ancestor, aspect: aspect) as T;
}
_hadUnsatisfiedDependencies = true;
return null;
}
@override
InheritedWidget dependOnInheritedElement(InheritedElement ancestor, { Object? aspect }) {
...
_dependencies ??= HashSet<InheritedElement>();
_dependencies!.add(ancestor);
// there this Is the current Element example
ancestor.updateDependencies(this, aspect);
return ancestor.widget;
}
}
We are Element You can see in the class , Called before us dependOnInheritedWidgetOfExactType() In the method , Will be called to dependOnInheritedElement() Method , It will call our current ShareDataWidget The corresponding InheritedElement Of updateDependencies() Method .
class InheritedElement extends ProxyElement {
...
@protected
void updateDependencies(Element dependent, Object? aspect) {
setDependencies(dependent, null);
}
@protected
void setDependencies(Element dependent, Object? value) {
_dependents[dependent] = value;
}
}
That is to say, when one of us Widget By calling ShareDataWidget Of of When using static methods , Just register yourself . In this way, subsequent updates can be notified .
So use dependOnInheritedWidgetOfExactType() Method we can see that this will register dependencies , So when the data is updated , The children of these dependencies Widget Will be called to didChangeDependencies() Method , Then they all need to be done build().
If we just want ShareDataWidget The data of , I don't want to didChangeDependencies() Called , Then use another method getElementForInheritedWidgetOfExactType<T extends InheritedWidget>(), hold ShareDataWidget Of of The method is rewritten as follows :
static ShareDataWidget of(BuildContext context) {
//return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
return context.getElementForInheritedWidgetOfExactType<ShareDataWidget>().widget;
}
abstract class Element extends DiagnosticableTree implements BuildContext {
...
@override
InheritedElement? getElementForInheritedWidgetOfExactType<T extends InheritedWidget>() {
...
final InheritedElement? ancestor = _inheritedWidgets == null ? null : _inheritedWidgets![T];
return ancestor;
}
...
}
getElementForInheritedWidgetOfExactType<T extends InheritedWidget>() Method heel dependOnInheritedWidgetOfExactType() The difference is that there is no registration relationship .
summary
- Realization
InheritedWidget, stayupdateShouldNotify()It is written in the method that what conditions will trigger the reminder - adopt
context.dependOnInheritedWidgetOfExactType()Method , Both let son Child Access to data , At the same time, it also plays a role Child Their own Element Sign up toInheritedWidgetin . - When data changes , Trigger to
InheritedWidgetImplementation classupdate()Method time , It will traverse the previously registered Element list , And then call theirdidChangeDependencies()Method , next Framework Would callbuildMethod .
边栏推荐
猜你喜欢

OPenGL 基本知识(根据自己理解整理)

Xml的(DTD,xml解析,xml建模)

Wrong arrangement (lottery, email)

错排问题 (抽奖,发邮件)

Ripper of vulnhub

vulnhub之tomato(西红柿)

The tutor put forward 20 pieces of advice to help graduate students successfully complete their studies: first, don't plan to take a vacation

Laravel time zone timezone

Groovy测试类 和 Junit测试

Kibana - installation and configuration of kibana
随机推荐
并发编程-单例
Systemverilog-- OOP--对象的拷贝
Vulnhub's Tomato (tomato)
vulnhub之GeminiInc v2
Wrong arrangement (lottery, email)
CGroup introduction
PHP導出word方法(一mht)
OPenGL 基本知识(根据自己理解整理)
Concurrent programming - singleton
Hongmeng third training (project training)
typeScript
Colleagues wrote a responsibility chain model, with countless bugs
Go language to realize static server
MCDF实验1
Introduction to the implementation principle of rxjs observable filter operator
ArcGIS application (XXI) ArcMap method of deleting layer specified features
Master and backup role election strategy in kept
shardingSphere分库分表<3>
Redis 笔记 01:入门篇
STL教程9-容器元素深拷贝和浅拷贝问题