Flutter报错:notifyListeners仅能在ChangeNotifier子类实例成员中使用
解决Flutter中TransformationController.notifyListeners()调用报错问题
你遇到的错误是因为notifyListeners()是ChangeNotifier类的受保护方法,只能在它的子类内部调用,无法从外部直接触发。TransformationController作为ChangeNotifier的子类,外部代码无权直接调用这个方法。
解决方法
推荐方案:通过修改controller的value触发自动通知
TransformationController的状态更新依赖其value属性,当你修改value时,它会自动调用内部的notifyListeners()通知所有监听者。如果你的场景只是需要触发界面更新、没有实际修改矩阵,可以通过克隆当前value并重新赋值的方式触发更新:
// 替换报错的transformationController.notifyListeners()这一行 transformationController.value = transformationController.value.clone();
这种方式既遵守了类的封装规则,又能触发所有依赖该controller的界面组件更新。
备选方案:自定义子类暴露notifyListeners(不推荐)
如果确实需要手动触发通知,可以创建自定义的TransformationController子类,把notifyListeners方法暴露出来,但这种做法会破坏类的封装性,仅在特殊场景下使用:
class CustomTransformationController extends TransformationController { @override void notifyListeners() { super.notifyListeners(); } }
之后将你的transformationController替换为这个自定义类的实例,就能在外部调用notifyListeners()了。
为什么setState无效?
你之前用setState没效果,是因为界面中依赖TransformationController的组件(比如InteractiveViewer)是监听controller的状态变化,而非Widget自身的state。setState只能刷新当前Widget树中依赖state的部分,无法触发依赖controller的组件更新。
修改后的完整代码示例
void _addButton(LongPressStartDetails details) async { setState(() { animatedIndex = chips.length; final chipEntry = ChipEntry(offset: transformationController.toScene(details.localPosition)); marker = chipEntry; chips = [marker]; labelNumber++; }); await controller.forward(from: 0.0); animatedIndex = -1; // 替换报错行的代码 transformationController.value = transformationController.value.clone(); SharedPreferences prefs = await SharedPreferences.getInstance(); double encodedX = marker.offset.dx; double encodedY = marker.offset.dy; prefs.setDouble('chipx', encodedX); prefs.setDouble('chipy', encodedY); }
内容的提问来源于stack exchange,提问作者Mat Koffman
相关产品推荐
相关产品推荐

