flutter riverpod从ChangeNotifier转换为使用StateNotifier
为了使用 StateNotifier
,我们需要首先确保你的项目已经添加了 state_notifier
依赖。StateNotifier
是 riverpod
的一部分,但它位于独立的包中。
对于这样的转换,我们可以从一个简单的 ChangeNotifier
示例开始。让我们假设有一个类 MyModel
满足下列条件:
class MyModel extends ChangeNotifier {
int _counter = 0;
int get counter => _counter;
void increment() {
_counter++;
notifyListeners();
}
}
要将它转换为使用 StateNotifier
,我们需要进行几个步骤。
首先,我们需要将 _counter
私有属性换成 int
类型的状态。
class MyModel extends StateNotifier<int> {
MyModel() : super(0);
void increment() {
state++;
}
}
然后,我们需要在提供器中进行一些更改。如果你使用的是 ChangeNotifierProvider
,那么你就需要将它换成 StateNotifierProvider
。
final myModelProvider = ChangeNotifierProvider((ref) => MyModel());
// becomes
final myModelProvider = StateNotifierProvider<MyModel, int>((ref) => MyModel());
最后,我们需要根据状态直接更改我们的使用方法。
final counter = useProvider(myModelProvider.select((value) => value.counter));
// becomes
final counter = useProvider(myModelProvider);
完成以上步骤后,我们就成功地将 ChangeNotifier
转换为使用 StateNotifier
了。
MyModel
有多个值的处理counter
name
如果 MyModel
类有多个值,例如叫做 _counter
和 _name
,你将需要创建一个新的类来持有这些状态。然后,你的 StateNotifier
类将维护这个新的状态对象。
让我们用下面的代码演示:
首先,我们创建一个新的 State
类来存储 _counter
和 _name
:
class MyState {
final int counter;
final String name;
MyState(this.counter, this.name);
}
然后,我们可以将 MyModel
修改为管理 MyState
而非独立的字段:
class MyModel extends StateNotifier<MyState> {
MyModel() : super(MyState(0, ''));
void increment() {
state = MyState(state.counter + 1, state.name);
}
void setName(String name) {
state = MyState(state.counter, name);
}
}
在这里,每次我们的状态改变时,我们都在创建一个新的 MyState
实例。这样可以确保状态的不变性,这是 Redux 和其他状态管理库的主要原则。
最后,你的提供器和使用方法将需要相应地更新:
final myModelProvider = StateNotifierProvider<MyModel, MyState>((ref) => MyModel());
// Usage
final myState = useProvider(myModelProvider);
// Access counter and name via myState.counter and myState.name respectively
你还可以通过 myModelProvider.select
进行更细力度的选择。
final counter = useProvider(myModelProvider.select((value) => value.counter));
final name = useProvider(myModelProvider.select((value) => value.name));
这就是如何处理具有多个字段的 StateNotifier
。
模型继承自MyModel
扩展变量的处理
假设你有一个继承自 MyModel
的模型,此模型扩展了更多的变量。对于这个问题有两种可能的方法。
方法一:扩展状态类
你可以扩展你的 MyState
类,并在子类中添加新的变量。
例如:
class ExtendedState extends MyState {
final String extraVariable;
ExtendedState(counter, name, this.extraVariable) : super(counter, name);
}
然后,你可以创建一个新的 StateNotifier
来使用你的 ExtendedState
:
class ExtendedModel extends StateNotifier<ExtendedState> {
ExtendedModel() : super(ExtendedState(0, '', ''));
void updateExtraVariable(String newValue) {
state = ExtendedState(state.counter, state.name, newValue);
}
}
方法二:组合 StateNotifier
类
另一种方法是你可以创建一个新的 StateNotifier
,维护它自己的状态,并依赖你的初始 MyModel
。这就像组合不同的 ChangeNotifier
类一样可以实现状态的共享。
例如:
class ExtraModel extends StateNotifier<String> {
final MyModel myModel;
ExtraModel(this.myModel) : super('') {
myModel.addListener(update);
}
@override
void dispose() {
myModel.removeListener(update);
super.dispose();
}
void update() {
state = 'new state based on myModel: ${myModel.state}';
}
}
这些都是根据你的具体需要选择的方法-你可能会发现,扩展你的状态类最简单,但如果你的状态类已经很复杂,或者你想要交叉引用不同的状态,那么组合 StateNotifier
类可能会是一个好方法。