Flutter中如何将Provider的ConsumerN迁移至Riverpod?
Flutter Provider 转 Riverpod 迁移问题解答
问题背景
我正尝试将Flutter代码从Provider迁移至Riverpod,当前部分代码实现如下:
原Provider视图代码:
class SomeViewOutput extends StatelessWidget { const PayoutFormOutput({Key? key}) : super(key: key); @override Widget build(BuildContext context) { final Widget someWidget = Consumer6<A, B, C, D, E, F>( builder: (context, a, b, c, d, e, f, _) { var total = a.value + b.value + c.value + d.value + e.value + f.value; return ListTile( dense: true, title: Text("Total", style: style), trailing: Text(total, style: style)); }); // ....do something else } }
通知器类定义:
import 'package:flutter/foundation.dart'; class MyState with ChangeNotifier { String field; double value; MyState({this.value = 0.0, this.field = 'No'}); void set(double value) { this.value = value; notifyListeners(); } void select(String field) { this.field = field; } } class A extends MyState {} class B extends MyState {} class C extends MyState {} class D extends MyState {} class E extends MyState {} class F extends MyState {}
我是Riverpod新手,尝试转换代码,写出了如下实现:
final a = ChangeNotifierProvider<MyState>((ref) { return MyState(); }); final b = ChangeNotifierProvider<MyState>((ref) { return MyState(); }); final c = ChangeNotifierProvider<MyState>((ref) { return MyState(); }); final d = ChangeNotifierProvider<MyState>((ref) { return MyState(); }); final e = ChangeNotifierProvider<MyState>((ref) { return MyState(); }); final f = ChangeNotifierProvider<MyState>((ref) { return MyState(); }); class MyConsumer6 extends ConsumerWidget { const MyConsumer6({Key? key}) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { double aValue = ref.watch(a).value; double bValue = ref.watch(b).value; double cValue = ref.watch(c).value; double dValue = ref.watch(d).value; double eValue = ref.watch(e).value; double fValue = ref.watch(f).value; var total = aValue + bValue + cValue + dValue + eValue + fValue; return ListTile( dense: true, title: Text("Total", style: style), trailing: Text(total, style: style)); } }
请问这是正确的迁移方式吗?另外,如果从ChangeNotifierProvider切换至StateNotifierProvider会有哪些变化?
回答
一、当前迁移方式的正确性与优化点
你的迁移思路是对的,但存在一处小问题,还有可优化的地方:
- Provider类型匹配问题:原代码中
A-F都是MyState的子类,但你定义的Provider返回的是MyState实例,应该改成对应子类的实例,否则无法区分不同的状态类:final a = ChangeNotifierProvider<A>((ref) => A()); final b = ChangeNotifierProvider<B>((ref) => B()); // 同理c/d/e/f都改成对应子类 - 无需单独定义MyConsumer6:你可以不用专门写一个
MyConsumer6组件,直接在原SomeViewOutput里通过Consumer或者将SomeViewOutput改成ConsumerWidget来实现,更简洁:
另外注意原代码中class SomeViewOutput extends ConsumerWidget { const SomeViewOutput({Key? key}) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { final aValue = ref.watch(a).value; final bValue = ref.watch(b).value; final cValue = ref.watch(c).value; final dValue = ref.watch(d).value; final eValue = ref.watch(e).value; final fValue = ref.watch(f).value; var total = aValue + bValue + cValue + dValue + eValue + fValue; final someWidget = ListTile( dense: true, title: Text("Total", style: style), trailing: Text(total.toString(), style: style), // 注意:total是double类型,需转成字符串 ); // ....do something else return ...; } }Text(total)会报错,因为total是double类型,需要转成字符串Text(total.toString())。
二、切换至StateNotifierProvider的变化
StateNotifier是Riverpod推荐的状态管理方案之一,相比ChangeNotifier有更严格的不可变状态约束,主要变化如下:
- 状态类改为不可变:需要定义一个不可变的状态类,替代原来的可变
MyState:// 不可变状态类,所有字段用final class MyImmutableState { final String field; final double value; const MyImmutableState({this.value = 0.0, this.field = 'No'}); // 提供copyWith方法,用于生成新状态 MyImmutableState copyWith({ String? field, double? value, }) { return MyImmutableState( field: field ?? this.field, value: value ?? this.value, ); } } - StateNotifier替代ChangeNotifier:不再使用
with ChangeNotifier,而是继承StateNotifier,状态更新必须通过生成新的状态对象:class MyStateNotifier extends StateNotifier<MyImmutableState> { MyStateNotifier() : super(const MyImmutableState()); void set(double value) { // 通过copyWith生成新状态,替换旧状态 state = state.copyWith(value: value); } void select(String field) { state = state.copyWith(field: field); } } // 如果需要不同的子类,可以继续继承MyStateNotifier class AStateNotifier extends MyStateNotifier {} - Provider定义变化:使用
StateNotifierProvider替代ChangeNotifierProvider:final aProvider = StateNotifierProvider<AStateNotifier, MyImmutableState>((ref) => AStateNotifier()); final bProvider = StateNotifierProvider<BStateNotifier, MyImmutableState>((ref) => BStateNotifier()); // 同理定义c/d/e/f的Provider - 监听状态的方式:通过
ref.watch直接获取不可变状态对象,无需担心状态突变:final aState = ref.watch(aProvider); double aValue = aState.value; - 核心优势:
- 不可变状态避免了意外的状态突变,代码更安全;
- StateNotifier只会在状态真正变化时通知监听者,性能更优;
- 状态变更逻辑更清晰,所有状态修改都集中在StateNotifier内部。
内容的提问来源于stack exchange,提问作者Randomize
相关产品推荐
相关产品推荐

