使用Provider触发A InspectionFormProvider已释放后使用错误的原因排查
核心成因
直接复用外部Provider实例,生命周期失控
你在ChangeNotifierProvider的create方法里返回了一个外部的inspectionFormProvider实例,而非在create内部创建新实例。当Provider关联的Widget被销毁时,框架会自动调用该实例的dispose()方法释放资源。但按钮的onPressed回调直接持有这个外部实例的引用,一旦实例被销毁,点击按钮调用insertItem()就会触发"已销毁实例被使用"的错误。未通过Widget树上下文获取存活的Provider实例
按钮逻辑里没有通过context获取当前Widget树中存活的Provider实例,而是直接使用外部引用。这种方式完全脱离了Provider框架的生命周期管理,无法感知实例是否已被销毁。Provider生命周期与使用范围不匹配
当前ChangeNotifierProvider的子Widget是Row,一旦Row被移除出Widget树,对应的Provider实例就会被销毁。但按钮回调仍然持有该实例的引用,后续点击必然访问已释放的对象。
修复方案
在
create内部创建新实例
让Provider框架管理实例的生命周期,避免外部复用:ChangeNotifierProvider( create: (_) => InspectionFormProvider(), // 内部生成新实例 child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // ... 其余代码 ], ), )通过
context获取存活的Provider实例
修改按钮的onPressed逻辑,通过上下文获取当前有效的Provider:ElevatedButton.icon( icon: Icon(...), label: Text(...), onPressed: () { // 用listen: false避免不必要的监听 Provider.of<InspectionFormProvider>(context, listen: false).insertItem(); }, )调整Provider层级(按需)
如果InspectionFormProvider需要跨多个Widget共享,或者生命周期长于当前Row,可以将ChangeNotifierProvider提升到更高层级(比如页面根Widget、MaterialApp),防止实例被过早销毁。
内容的提问来源于stack exchange,提问作者Unknown Developer

