Flutter页面与Tab切换时避免重复加载数据的方案
问题描述
- 进入应用首页时从API加载数据,导航到其他页面返回首页、切换页面内3个Tab时,数据都会重新加载
- 需求:仅加载一次初始数据,同时能同步显示数据库更新的变化,当前使用
StreamBuilder实现但未达到预期效果
现有代码
Stream定义代码
late Stream<AdminPostModel> stream = Stream.periodic(Duration(seconds: 3)) .asyncMap((event) async => await getCurrentAdminPost()); Future<AdminPostModel> getCurrentAdminPost() async { var url = "https:myURL.php?id=$getUserId&pageNo=$currentPage"; var response = await http.get(Uri.parse(url)); var jsondata = jsonDecode(response.body.toString()); if (response.statusCode == 200) { return AdminPostModel.fromJson(jsondata); } else { return AdminPostModel.fromJson(jsondata); } }
StreamBuilder列表构建代码
Expanded( child: StreamBuilder<AdminPostModel>( stream: stream, builder: (context, snapshot) { if (snapshot.hasData) { return ....Code
解决方案
1. 避免Stream重复创建
当前late Stream在页面重建(返回首页、Tab切换)时会重新初始化,导致重复请求。将Stream创建逻辑移到initState中,只初始化一次:
Stream<AdminPostModel>? _stream; @override void initState() { super.initState(); _stream = Stream.periodic(const Duration(seconds: 3)) .asyncMap((_) => getCurrentAdminPost()); }
2. 优化数据请求逻辑
去掉冗余的重复返回,增加错误处理逻辑:
Future<AdminPostModel> getCurrentAdminPost() async { final url = "https:myURL.php?id=$getUserId&pageNo=$currentPage"; final response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { return AdminPostModel.fromJson(jsonDecode(response.body)); } else { // 抛出错误,让StreamBuilder捕获并处理异常状态 throw Exception('请求失败,状态码:${response.statusCode}'); } }
3. 管理Stream生命周期
页面销毁时取消订阅,避免内存泄漏:
StreamSubscription? _subscription; @override void initState() { super.initState(); _stream = Stream.periodic(const Duration(seconds: 3)) .asyncMap((_) => getCurrentAdminPost()); _subscription = _stream?.listen((_) {}); } @override void dispose() { _subscription?.cancel(); super.dispose(); }
4. 优化更新触发方式(可选)
如果数据库支持WebSocket或推送通知,替换Stream.periodic轮询为事件触发式Stream,仅在收到更新通知时发起请求,减少无效API调用。
内容的提问来源于stack exchange,提问作者Taki Rajani
相关产品推荐
相关产品推荐

