当前位置:网站首页>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 toInheritedWidget
in . - When data changes , Trigger to
InheritedWidget
Implementation classupdate()
Method time , It will traverse the previously registered Element list , And then call theirdidChangeDependencies()
Method , next Framework Would callbuild
Method .
边栏推荐
猜你喜欢
随机推荐
Vulnhub's presidential
STL教程10-容器共性和使用场景
在CoreOS下部署WordPress实例教程
Symlink(): solution to protocol error in PHP artisan storage:link on win10
(构造笔记)MIT reading部分学习心得
typeScript
Quantitative calculation research
vulnhub之cereal
previous permutation lintcode51
PHP導出word方法(一mht)
Niuniu's team competition
Capturing and sorting out external Fiddler -- Conversation bar and filter [2]
Solve msvcp120d DLL and msvcr120d DLL missing
STL tutorial 10 container commonalities and usage scenarios
量化计算调研
外插散点数据
vulnhub之Ripper
Optimize interface performance
Simple factory and factory method mode
R language uses grid of gridextra package The array function combines multiple visual images of the lattice package horizontally, and the ncol parameter defines the number of columns of the combined g