Provider直接使用与赋值给变量的区别及子组件调用方案咨询
直接调用不生效的原因
你遇到的现象90%以上的场景和Provider.of的listen参数默认值有关:Provider.of<T>(context)默认listen = true,这个取值只允许在组件的build阶段调用,作用是让当前组件监听Provider的状态变化,状态更新时触发组件重建。
如果你是在点击回调、initState等非build阶段的上下文里直接调用Provider.of<MyProvider>(context).getSomething(),会触发运行时异常,表现出来就是逻辑没执行、没有生效。
而你提前在build方法顶部把Provider实例赋值给变量,相当于在合法的build阶段拿到了实例,后续不管在什么场景调用这个实例的方法,都不需要再走context查找逻辑,自然不会报错。
如果需要在非build阶段直接调用,只要显式传入listen: false即可:
Provider.of<MyProvider>(context, listen: false).getSomething();
每个子Widget都声明Provider会不会有问题
不会有性能问题。Provider.of的查找逻辑是基于Element树的缓存实现,时间复杂度为O(1),多次调用不会带来额外的性能开销。
唯一需要注意的是listen参数的取值:
- 如果当前子Widget需要根据Provider的状态变化刷新UI,保留默认
listen: true即可 - 如果当前子Widget只需要调用Provider的方法、不需要监听状态变化,建议显式指定
listen: false,避免触发不必要的组件重建
要不要通过构造参数传递Provider
根据组件的使用场景选择即可:
- 如果是通用型组件,不耦合特定业务的Provider,通过构造参数传递对应的数据/实例更合理,组件的可复用性更高
- 如果是业务专属组件,只会和当前业务的Provider配合使用,直接通过
Provider.of获取实例更高效,避免嵌套层级深的时候出现层层传参的冗余代码
内容的提问来源于stack exchange,提问作者satoru_02
相关产品推荐
相关产品推荐

