记录项目工程化步骤
项目基本架构

基本结构:
- domain下写model,然后state包住model用于管理其状态
- presentation下面写展示内容,分为controller和主页面,controller里面操作数据,页面仅展示数据
基本流程
先请求一遍接口,根据接口返回值,用jsonToDart或者jsonToFreezed,或者是直接用AI生成freezed文件,
prompts:把这段 JSON 转成 Dart 的 Freezed 类,要包含 Default 值,并且处理好嵌套关系,然后terminal跑这一段flutter pub run build_runner build --delete-conflicting-outputs生成freezed和g文件。state包住model
1
2
3
4
5
6
7
8
9
10
11
class UserProfileState with _$UserProfileState {
const factory UserProfileState({
// 核心数据
UserProfileModel? userProfile,
// UI 状态
(true) bool isLoading,
(false) bool permission,
}) = _UserProfileState;
}类似于这样的结构
写controller,对于网络数据这种异步获取的数据,Riverpod 2.0 更推荐把
build变成异步的 (Future),这样就不用手动管理isLoading,也不用手动触发loadData,一切由 Riverpod 自动管理。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Future<UserProfileState> build(int userId) async {
final data = await RequestUtils.ins().askFor(
RequestUtils.urls['gc_mine']['getUserInfo'],
method: "GET",
data: {"visitedUserId": userId});
final model = UserProfileModel.fromJson(data);
return UserProfileState(
isLoading: false,
userProfile: model,
);
}
Future<void> refresh() async {
state = const AsyncLoading();
state = await AsyncValue.guard(() => build(userId));
}类似于这样的写法
在页面中获取数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24Widget build(BuildContext context) {
final asyncState = ref.watch(profileControllerProvider(widget.userId));
return asyncState.when(
data: (state) {
// 这里拿到了 UserProfileState
return Scaffold(
backgroundColor: GC.backGroundColor,
body: // 这里拿数据办事
},
error: (err, stack) => Text('Error: $err'),
loading: () => Scaffold(
backgroundColor: GC.backGroundColor,
body: Center(
child: SizedBox(
width: 32.w,
height: 32.w,
child: const CircularProgressIndicator(
strokeWidth: 2.5,
),
),
),
),
);
}写法也比较简单。
工程化写法有助于理解,这样不会发生过个一年半载回来看代码发现自己也不理解的情况。