Flutter开发:API请求时如何在AppBar中显示LinearProgressIndicator
在Flutter AppBar中根据API请求状态显示进度条
核心思路
- 用状态变量跟踪当前是否有API请求在进行
- API请求发起时标记为加载状态,请求完成(成功/失败)后取消加载状态
- 在AppBar中根据状态条件渲染
LinearProgressIndicator
具体实现步骤
1. 管理加载状态
方案一:局部状态(适用于单个页面)
如果你的MenuScreen是StatefulWidget,直接在状态类中维护加载状态:
class MenuScreen extends StatefulWidget { @override State<MenuScreen> createState() => _MenuScreenState(); } class _MenuScreenState extends State<MenuScreen> { bool _isLoading = false; // 更新加载状态的方法 void _updateLoadingStatus(bool status) { setState(() { _isLoading = status; }); } }
方案二:全局状态(适用于多页面共享加载状态)
如果需要在多个页面同步显示加载状态,用ChangeNotifier实现全局状态管理:
class LoadingState extends ChangeNotifier { bool _isLoading = false; bool get isLoading => _isLoading; void setLoading(bool status) { _isLoading = status; notifyListeners(); } }
在main.dart中注册全局状态:
void main() { runApp( ChangeNotifierProvider( create: (_) => LoadingState(), child: const MyApp(), ), ); }
2. 改造API请求工具方法
不管用http、dio还是其他网络库,都要在请求前后更新加载状态,确保请求结束后(无论成功失败)进度条都会隐藏。
示例:基于http库的改造
class ApiService { // 全局状态方案:注入LoadingState final LoadingState? loadingState; // 局部状态方案:传递状态更新回调 final void Function(bool)? updateLoading; ApiService({this.loadingState, this.updateLoading}); Future<Map<String, dynamic>> login(String username, String password) async { // 标记加载开始 loadingState?.setLoading(true); updateLoading?.call(true); try { final response = await http.post( Uri.parse('https://your-api-domain.com/login'), body: {'username': username, 'password': password}, ); return jsonDecode(response.body); } catch (e) { // 错误处理逻辑 rethrow; } finally { // 请求结束,取消加载状态 loadingState?.setLoading(false); updateLoading?.call(false); } } Future<List<dynamic>> fetchServerData() async { loadingState?.setLoading(true); updateLoading?.call(true); try { final response = await http.get(Uri.parse('https://your-api-domain.com/data')); return jsonDecode(response.body); } catch (e) { rethrow; } finally { loadingState?.setLoading(false); updateLoading?.call(false); } } }
进阶:dio拦截器统一处理
如果用dio,可以通过拦截器统一管理加载状态,避免重复代码:
class LoadingInterceptor extends Interceptor { final LoadingState loadingState; LoadingInterceptor(this.loadingState); @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { loadingState.setLoading(true); super.onRequest(options, handler); } @override void onResponse(Response response, ResponseInterceptorHandler handler) { loadingState.setLoading(false); super.onResponse(response, handler); } @override void onError(DioError err, ErrorInterceptorHandler handler) { loadingState.setLoading(false); super.onError(err, handler); } } // 初始化dio时添加拦截器 final dio = Dio(); dio.interceptors.add(LoadingInterceptor(LoadingState()));
3. 在AppBar中添加进度条
把LinearProgressIndicator作为AppBar的bottom属性,根据加载状态显示/隐藏:
局部状态方案
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Menu Screen'), // 根据加载状态显示进度条 bottom: _isLoading ? const PreferredSize( preferredSize: Size.fromHeight(2.0), child: LinearProgressIndicator(), ) : null, ), body: // 页面内容 ); }
全局状态方案
用Consumer监听全局状态变化:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Menu Screen'), bottom: Consumer<LoadingState>( builder: (context, state, child) { return state.isLoading ? const PreferredSize( preferredSize: Size.fromHeight(2.0), child: LinearProgressIndicator(), ) : null; }, ), ), body: // 页面内容 ); }
注意事项
- 必须用
finally块(或拦截器的响应/错误回调)取消加载状态,避免请求失败后进度条一直显示 - 如果有多个并发请求,可以把
isLoading改成计数器(请求开始+1,结束-1),计数器>0时显示进度条,防止进度条闪跳
内容的提问来源于stack exchange,提问作者ElMexicanitox3
相关产品推荐
相关产品推荐

