为什么要为订阅和 ChangeNotifiers 实现 didUpdateWidget?
Why should didUpdateWidget be implemented for subscriptions and ChangeNotifiers?
我创建了一个自定义小部件,它监听 ChangeNotifier
并在通知程序触发时调用提供的回调。这用于在通知程序更改时执行一次性任务,例如导航。
一切似乎都很好,但我偶然发现了 documentation of didUpdateWidget
,它指出:
If a State's build method depends on an object that can itself change state, for example a ChangeNotifier or Stream, or some other object to which one can subscribe to receive notifications, then be sure to subscribe and unsubscribe properly in initState, didUpdateWidget, and dispose:
- In initState, subscribe to the object.
- In didUpdateWidget unsubscribe from the old object and subscribe to the new one if the updated widget configuration requires replacing the object.
- In dispose, unsubscribe from the object.
出于显而易见的原因,我正在处理第一点和最后一点,但有人可以阐明为什么我还必须实施 didUpdateWidget
吗?如果我不这样做会出什么问题?
奖金问题:我还没有在我的应用程序中使用提供程序。它是否提供开箱即用的类似功能?我找不到这样的东西。
我的插件代码:
class ChangeNotifierListener<T extends ChangeNotifier> extends StatefulWidget {
final Widget child;
final T changeNotifier;
final void Function(T changeNotifier) onChanged;
ChangeNotifierListener(
{@required this.child,
@required this.changeNotifier,
@required this.onChanged});
@override
_ChangeNotifierListenerState createState() =>
_ChangeNotifierListenerState<T>();
}
class _ChangeNotifierListenerState<T extends ChangeNotifier>
extends State<ChangeNotifierListener<T>> {
VoidCallback _callback;
@override
Widget build(BuildContext context) => widget.child;
@override
void initState() {
super.initState();
_callback = () {
widget.onChanged(widget.changeNotifier);
};
widget.changeNotifier.addListener(_callback);
}
@override
void dispose() {
widget.changeNotifier.removeListener(_callback);
super.dispose();
}
}
文档的这一部分是关于如何使用不同的参数重建小部件的可行性。
例如,对于 StreamBuilder
,第一个构建可能类似于:
StreamBuilder(
stream: Stream.value(42),
builder: ...
)
然后发生了一些变化,StreamBuilder
重建为:
StreamBuilder(
stream: Stream.value(21),
builder: ...
)
在这种情况下,stream
发生了变化。因此,StreamBuilder
需要停止收听上一个Stream
并收听新的。
这将通过以下方式完成 didUpdateWidget
:
StreamSubscription<T> subscription;
@override
void didUpdateWidget(StreamBuilder<T> oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.stream != oldWidget.stream) {
subscription?.cancel();
subscription = widget.stream?.listen(...);
}
}
同样的逻辑适用于 ChangeNotifier
和任何其他可观察对象。
我创建了一个自定义小部件,它监听 ChangeNotifier
并在通知程序触发时调用提供的回调。这用于在通知程序更改时执行一次性任务,例如导航。
一切似乎都很好,但我偶然发现了 documentation of didUpdateWidget
,它指出:
If a State's build method depends on an object that can itself change state, for example a ChangeNotifier or Stream, or some other object to which one can subscribe to receive notifications, then be sure to subscribe and unsubscribe properly in initState, didUpdateWidget, and dispose:
- In initState, subscribe to the object.
- In didUpdateWidget unsubscribe from the old object and subscribe to the new one if the updated widget configuration requires replacing the object.
- In dispose, unsubscribe from the object.
出于显而易见的原因,我正在处理第一点和最后一点,但有人可以阐明为什么我还必须实施 didUpdateWidget
吗?如果我不这样做会出什么问题?
奖金问题:我还没有在我的应用程序中使用提供程序。它是否提供开箱即用的类似功能?我找不到这样的东西。
我的插件代码:
class ChangeNotifierListener<T extends ChangeNotifier> extends StatefulWidget {
final Widget child;
final T changeNotifier;
final void Function(T changeNotifier) onChanged;
ChangeNotifierListener(
{@required this.child,
@required this.changeNotifier,
@required this.onChanged});
@override
_ChangeNotifierListenerState createState() =>
_ChangeNotifierListenerState<T>();
}
class _ChangeNotifierListenerState<T extends ChangeNotifier>
extends State<ChangeNotifierListener<T>> {
VoidCallback _callback;
@override
Widget build(BuildContext context) => widget.child;
@override
void initState() {
super.initState();
_callback = () {
widget.onChanged(widget.changeNotifier);
};
widget.changeNotifier.addListener(_callback);
}
@override
void dispose() {
widget.changeNotifier.removeListener(_callback);
super.dispose();
}
}
文档的这一部分是关于如何使用不同的参数重建小部件的可行性。
例如,对于 StreamBuilder
,第一个构建可能类似于:
StreamBuilder(
stream: Stream.value(42),
builder: ...
)
然后发生了一些变化,StreamBuilder
重建为:
StreamBuilder(
stream: Stream.value(21),
builder: ...
)
在这种情况下,stream
发生了变化。因此,StreamBuilder
需要停止收听上一个Stream
并收听新的。
这将通过以下方式完成 didUpdateWidget
:
StreamSubscription<T> subscription;
@override
void didUpdateWidget(StreamBuilder<T> oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.stream != oldWidget.stream) {
subscription?.cancel();
subscription = widget.stream?.listen(...);
}
}
同样的逻辑适用于 ChangeNotifier
和任何其他可观察对象。