Flutter:将Riverpod Provider代码重构为控制器与服务架构
Flutter Riverpod代码重构:分离Controller与Service
原有可运行代码
@freezed class LessonDOState with _$LessonDOState { const factory LessonDOState( {@Default([]) List<LessonDO> lessons, @Default({}) Map<int, LessonDO> lessonMap, @Default(true) isLoading}) = _LessonDOState; const LessonDOState._(); } final lessonsProvider = StateNotifierProvider<LessonDONotifier, LessonDOState>( (ref) => LessonDONotifier()); class LessonDONotifier extends StateNotifier<LessonDOState> { LessonDONotifier() : super(const LessonDOState()) { loadLessonDOs(); } loadLessonDOs() async { final lessonsData = await rootBundle.rootBundle.loadString('assets/json/lessons.json'); // 原代码遗漏JSON解析步骤,重构时已补充 final lessonsList = jsonDecode(lessonsData) as List; final lessons = lessonsList.map((e) => LessonDO.fromJson(e)).toList(); final lessonMap = listToMap(lessons); final isLoading = lessons.isEmpty; state = state.copyWith( lessons: lessons, lessonMap: lessonMap, isLoading: isLoading); } Map<int, LessonDO> listToMap(List<LessonDO> lessons) { Map<int, LessonDO> map = {}; for (LessonDO lesson in lessons) { map[lesson.number!] = lesson; } return map; } }
重构后代码
按照Controller(Provider)与Service分离的思路,将数据获取逻辑抽离到Service层,Controller仅负责状态管理。
1. lesson_service.dart(Service层)
专注处理数据加载、解析与转换,封装数据获取细节:
final lessonService = Provider((ref) => LessonService()); class LessonService { Future<List<LessonDO>> loadLessons() async { try { final lessonsData = await rootBundle.loadString('assets/json/lessons.json'); final lessonsList = jsonDecode(lessonsData) as List; return lessonsList.map((e) => LessonDO.fromJson(e)).toList(); } catch (e) { rethrow; } } Map<int, LessonDO> convertLessonsToMap(List<LessonDO> lessons) { final Map<int, LessonDO> map = {}; for (final lesson in lessons) { if (lesson.number != null) { map[lesson.number!] = lesson; } } return map; } }
2. lesson_provider.dart(Controller层)
负责状态管理,依赖Service层获取数据,使用AsyncValue统一处理加载、成功、失败状态:
final lessonsProvider = StateNotifierProvider.autoDispose<LessonNotifier, AsyncValue<LessonDOState>>( (ref) => LessonNotifier(ref), ); class LessonNotifier extends StateNotifier<AsyncValue<LessonDOState>> { final AutoDisposeStateNotifierProviderRef _ref; late final LessonService _lessonService; LessonNotifier(this._ref) : super(const AsyncValue.data(LessonDOState())) { _lessonService = _ref.watch(lessonService); _loadLessons(); } Future<void> _loadLessons() async { state = const AsyncValue.loading(); final result = await AsyncValue.guard(() async { final lessons = await _lessonService.loadLessons(); final lessonMap = _lessonService.convertLessonsToMap(lessons); return LessonDOState( lessons: lessons, lessonMap: lessonMap, isLoading: false, ); }); state = result; } // 暴露外部重新加载数据的方法 Future<void> reloadLessons() => _loadLessons(); }
重构核心要点
- 职责分离:Service层专注数据操作,Controller层专注状态管理,降低耦合度,便于单元测试和代码复用。
- 状态统一管理:使用
AsyncValue封装加载、成功、失败三种状态,简化UI层的状态判断逻辑。 - 资源自动清理:使用
autoDispose修饰Provider,在不再被监听时自动释放资源,避免内存泄漏。 - 补全遗漏逻辑:原代码缺少JSON解析步骤,重构时已补充完整。
内容的提问来源于stack exchange,提问作者Yuriy N.
相关产品推荐
相关产品推荐

