成员 'notifyListeners' 只能在 'package:flutter/src/foundation/change_notifier.dart' 或测试中使用

The member 'notifyListeners' can only be used within 'package:flutter/src/foundation/change_notifier.dart' or a test

我正在使用 ChangeNotifier,我更改了它们的值并通知如下,

// Declare
ValueNotifier<bool> isDisplay = new ValueNotifier(false);

// Change value
isDisplay.value = false;
isDisplay.notifyListeners();

一切正常。但它会像下面那样发出警告,

我们能否通过适当的实施或其他方式解决此问题?

您不需要调用 notifyListeners,因为它会在设置新值时自动调用。

ChangeNotifierValueListener 这样的实现永远不需要手动调用 notifyListeners

我也遇到了这些错误,更具体地说,是那些 2:

The member 'notifyListeners' can only be used within instance members of subclasses of 'package:flutter/src/foundation/change_notifier.dart'.dart(invalid_use_of_protected_member)
The member 'notifyListeners' can only be used within 'package:flutter/src/foundation/change_notifier.dart' or a test.dart(invalid_use_of_visible_for_testing_member)

经过一些研究,我得出了一些结论和解决方案。觉得我应该分享给遇到这个问题的人。

问题

实际上它说的很明显,“如果你想调用 notifyListeners(),你必须在 ChangeNotifier 的子 class 或测试文件中执行它”

“但这是为什么呢?”可以理解,这是我的第二个问题。但在此之前,先了解一下 notifyListeners 方法到底是从哪里来的

notifyListeners 方法

如果您查看 ValueNotifier 的实现,它会扩展 ChangeNotifier class:

ChangeNotifier 有一个 notifyListeners() 方法(这就是我们首先可以使用此方法的原因)但不是通常的方式:

它受到保护。

@Dart 中的受保护注解 | doc

[@protected annotation] Indicates that the annotated instance member (method, getter, setter, operator, or field) m in a class or mixin C should only be referenced in specific locations.

A reference from within the library in which C is declared is valid. Additionally, a reference from within an instance member in C, or a class that extends, implements, or mixes in C (either directly or indirectly), or a mixin that uses C as a superclass constraint is valid. Additionally, a reference from within an instance member in an extension that applies to C is valid.”

更通俗的解释:它可以用在子class中,直接扩展(或混入)ChangeNotifier class 或在测试文件中。由于您想在您的逻辑代码中使用它,因此您必须执行本段的第一部分:“在您要调用 notifyListeners 方法的位置扩展或混合 ChangeNotifier。”

在哪里扩展(或混入)ChangeNotifier class?

您可能想在有状态或无状态小部件中使用它,并且由于 Dart 是 single-inheritance,您必须将 ChangeNotifier class“混合”到您的 class,但你错了。原因是 ChangeNotifier class 定义了它自己的 dispose 方法。由于 class 或混合到您的 class 的混合取代了以前继承的方法,现在您的 dispose 将是 ChangeNotifier 的 dispose而不是国家的 dispose.

记住,无论如何你都必须释放状态class使用的资源。如果你不在你的 State 中重写 dispose 方法,框架会为你做这件事,这很酷;但由于您刚刚更改了 dispose 方法的祖先,框架将不会触发所需的 dispose 方法。

因此,解决此问题的方法是,创建一个新的 class 来操纵值更改,并 扩展或混合 ChangeNotifier 到此 class。然后你可以随时随地调用 notifyListeners() 方法! (当然,不要调用 notifyListeners 除非你使用复杂的对象或发送相同的值

此外,这些 class 最好称为 'Controller'、'ViewModel'、'BLoC' 或任何其他名称以表明它们是 mutating/controlling 你的价值观并触发 UI 在需要时重建。 (首先你应该做什么,将你的 UI 与你的逻辑层分开)。

进一步阅读