面试题答案
一键面试整体实现方案
- 状态管理:
- 使用
ValueNotifier
或Provider
等状态管理方案。以ValueNotifier
为例,创建不同的ValueNotifier<bool>
分别表示每个网络请求的加载状态,如ValueNotifier<bool> userInfoLoading = ValueNotifier<bool>(false);
,ValueNotifier<bool> orderListLoading = ValueNotifier<bool>(false);
,ValueNotifier<bool> favoriteListLoading = ValueNotifier<bool>(false);
。 - 同时创建用于存储请求结果的变量,如
UserInfo? userInfo;
,List<Order>? orderList;
,List<Favorite>? favoriteList;
。
- 使用
- 网络请求:
- 使用
http
或dio
库进行网络请求。以dio
为例,定义获取用户信息、订单列表和收藏列表的方法,例如:
- 使用
Future<UserInfo> fetchUserInfo() async {
final response = await Dio().get('/user/info');
return UserInfo.fromJson(response.data);
}
Future<List<Order>> fetchOrderList() async {
final response = await Dio().get('/user/orders');
return (response.data as List).map((e) => Order.fromJson(e)).toList();
}
Future<List<Favorite>> fetchFavoriteList() async {
final response = await Dio().get('/user/favorites');
return (response.data as List).map((e) => Favorite.fromJson(e)).toList();
}
- 并发执行:
- 使用
Future.wait
方法并发执行多个网络请求,例如:
- 使用
try {
userInfoLoading.value = true;
orderListLoading.value = true;
favoriteListLoading.value = true;
final results = await Future.wait([
fetchUserInfo(),
fetchOrderList(),
fetchFavoriteList()
]);
userInfo = results[0];
orderList = results[1];
favoriteList = results[2];
} catch (e) {
// 处理错误
} finally {
userInfoLoading.value = false;
orderListLoading.value = false;
favoriteListLoading.value = false;
// 更新UI
setState(() {});
}
- UI展示:
- 在
build
方法中,根据ValueNotifier
的状态显示加载信息,如:
- 在
ValueListenableBuilder<bool>(
valueListenable: userInfoLoading,
builder: (context, value, child) {
if (value) {
return Text('正在获取用户信息...');
} else {
return userInfo!= null? Text('用户信息:${userInfo!.name}') : Container();
}
},
),
类似地处理订单列表和收藏列表的加载状态及结果展示。
可能遇到的难点及解决方法
- 错误处理:
- 难点:在并发请求中,某个请求失败可能需要适当处理,并且不影响其他请求的继续执行和最终结果处理。
- 解决方法:在
Future.wait
的catch
块中,对不同请求的错误进行分类处理。可以自定义异常类型,在每个请求方法中抛出特定异常,例如:
Future<UserInfo> fetchUserInfo() async {
try {
final response = await Dio().get('/user/info');
return UserInfo.fromJson(response.data);
} catch (e) {
throw UserInfoFetchException();
}
}
在Future.wait
的catch
块中:
try {
//...
} catch (e) {
if (e is UserInfoFetchException) {
// 处理用户信息获取错误
} else if (e is OrderListFetchException) {
// 处理订单列表获取错误
} else if (e is FavoriteListFetchException) {
// 处理收藏列表获取错误
}
}
- 内存管理:
- 难点:如果在请求过程中频繁更新状态,可能导致内存消耗增加和性能问题。
- 解决方法:合理使用状态管理方案,避免不必要的状态更新。例如使用
ValueNotifier
时,确保只有在真正需要更新UI时才触发value
的改变。同时,可以在页面销毁时及时释放相关资源,如取消未完成的网络请求(dio
可以使用CancelToken
来取消请求)。
- 网络延迟和超时:
- 难点:网络请求可能由于网络延迟或超时导致长时间等待,影响用户体验。
- 解决方法:在网络请求库中设置合理的超时时间,如
dio
可以通过options
设置超时:
Future<UserInfo> fetchUserInfo() async {
final response = await Dio().get('/user/info', options: Options(timeout: Duration(seconds: 5)));
return UserInfo.fromJson(response.data);
}
并且在界面上可以提供一个加载超时的提示,告知用户请求超时,让用户可以选择重试。