Riverpod的StateNotifier更新状态时如何获取更新前的旧状态
解决方案
步骤1:调整CitiesState类,新增copyWith方法
建议将属性改为final符合Riverpod不可变状态的设计规范,copyWith是Dart生态中处理不可变对象部分更新的常用方案:
import 'package:flutter_riverpod/flutter_riverpod.dart'; class CitiesState { final List<String> cities; final String selectedCity; CitiesState({required this.cities, required this.selectedCity}); // 新增copyWith方法,未传入的属性默认复用旧值 CitiesState copyWith({ List<String>? cities, String? selectedCity, }) { return CitiesState( cities: cities ?? this.cities, selectedCity: selectedCity ?? this.selectedCity, ); } }
步骤2:修改updateCitiesData方法,保留旧的选中城市值
可以通过state.whenOrNull安全读取不同状态下的旧值,容错性更高:
class ChooseCityPageModel extends StateNotifier<AsyncValue<CitiesState>> { ChooseCityPageModel() : super(AsyncValue.loading()); Future<void> updateCitiesData() async { // 先读取旧状态的selectedCity,拿不到则用默认值 final oldSelectedCity = state.whenOrNull( data: (stateData) => stateData.selectedCity, ) ?? "New York"; state = const AsyncValue.loading(); try { final latestCities = await myAPI.getAvailableCities(); state = AsyncValue.data( CitiesState( selectedCity: oldSelectedCity, cities: latestCities, ), ); // 用copyWith的写法更简洁,效果完全一致: // state.whenOrNull(data: (oldState) { // state = AsyncValue.data(oldState.copyWith(cities: latestCities)); // }); } catch (error, stackTrace) { // 新版本Riverpod要求AsyncValue.error传入堆栈追踪参数 state = AsyncValue.error(error, stackTrace); } } }
注意事项
- 你原代码中创建状态实例时类名写错了,你定义的状态类是
CitiesState,不要写成ChooseCityPageState - 后续如果需要单独修改选中城市,也可以直接用copyWith实现:
state = AsyncValue.data(state.value!.copyWith(selectedCity: '上海')) - 如果能确定调用更新方法时一定有成功加载的旧状态,也可以直接用
state.value?.selectedCity读取旧值,和whenOrNull写法效果一致
内容的提问来源于stack exchange,提问作者Agung
相关产品推荐
相关产品推荐

