基于Provider 5实现Flutter登录场景加载页展示的方案咨询
基于Provider 5实现登录加载逻辑方案
1. 定义业务状态类
继承ChangeNotifier封装加载状态和登录逻辑,所有状态变更统一在类内处理:
import 'package:flutter/foundation.dart'; class AuthViewModel extends ChangeNotifier { // 私有变量存储加载状态,避免外部直接修改 bool _isLoading = false; // 对外暴露只读的加载状态 bool get isLoading => _isLoading; Future<void> login(String account, String password) async { // 输入校验不通过直接返回 if (account.trim().isEmpty || password.trim().isEmpty) return; // 校验通过开启加载状态,通知监听者刷新UI _isLoading = true; notifyListeners(); try { // 此处替换为实际的登录请求、用户信息持久化逻辑 await Future.delayed(const Duration(seconds: 2)); // 模拟接口请求耗时 // 登录成功后可执行路由跳转逻辑 } catch (err) { // 可在此处添加登录失败的提示逻辑 if (kDebugMode) print("登录异常:$err"); } finally { // 无论请求成功/失败都关闭加载状态 _isLoading = false; notifyListeners(); } } }
2. 全局注册状态实例
在应用入口处注册ChangeNotifierProvider,让子树可以访问到AuthViewModel实例:
void main() { runApp( ChangeNotifierProvider( create: (context) => AuthViewModel(), child: const MyApp(), ), ); }
3. 登录页绑定状态
使用StatelessWidget即可实现需求,通过Selector精准监听加载状态变化,控制页面渲染逻辑:
import 'package:provider/provider.dart'; class LoginPage extends StatelessWidget { const LoginPage({super.key}); @override Widget build(BuildContext context) { // 用read获取ViewModel实例,点击事件不需要监听状态变化,性能更优 final authViewModel = context.read<AuthViewModel>(); final accountController = TextEditingController(); final pwdController = TextEditingController(); // Selector只监听isLoading字段的变化,避免不必要的UI重绘 return Selector<AuthViewModel, bool>( selector: (_, vm) => vm.isLoading, builder: (_, isLoading, __) { return isLoading ? const LoadingPage() : Scaffold( appBar: AppBar(title: const Text("登录")), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ TextField( controller: accountController, decoration: const InputDecoration(hintText: "请输入账号"), ), const SizedBox(height: 12), TextField( controller: pwdController, decoration: const InputDecoration(hintText: "请输入密码"), obscureText: true, ), const SizedBox(height: 24), ElevatedButton( onPressed: () => authViewModel.login( accountController.text, pwdController.text, ), child: const Text("登录"), ) ], ), ), ); }, ); } }
4. 基于flutter_spinKit实现加载页
import 'package:flutter_spinkit/flutter_spinkit.dart'; class LoadingPage extends StatelessWidget { const LoadingPage({super.key}); @override Widget build(BuildContext context) { return const Scaffold( body: Center( child: SpinKitFadingCircle( color: Colors.blueAccent, size: 48, ), ), ); } }
Flutter状态管理实操建议
- 拆分状态粒度:不要将全业务状态塞到同一个
ChangeNotifier中,按模块拆分状态类,比如用户模块、订单模块分别维护各自的状态,减少不必要的刷新范围 - 优先用
Selector替代Consumer:如果只需要监听状态中的某几个字段,用Selector可以精准控制刷新范围,性能远高于全量监听的Consumer - 逻辑收拢到状态类:UI层只负责事件触发和状态渲染,所有异步请求、数据校验、状态变更逻辑都统一放到对应的
ChangeNotifier中,降低耦合度,也方便后续单元测试 - 及时清理资源:在
ChangeNotifier的dispose方法中取消未完成的异步请求、销毁流订阅,避免内存泄漏 - 避免嵌套地狱:如果需要注册多个Provider,使用
MultiProvider来统一管理,提升代码可读性
内容的提问来源于stack exchange,提问作者delaram
相关产品推荐
相关产品推荐

