当前位置: 首页 > news >正文

AtomGit Flutter鸿蒙客户端:Provider状态管理

架构分层

项目的状态管理分为三层:

MultiProvider(应用根节点) ├── Provider<AtomGitApiClient> — 全局服务 ├── ChangeNotifierProvider<AuthProvider> — 全局状态 │ └── 各页面(按需创建) ├── ChangeNotifierProvider<RepoDetailProvider> ├── ChangeNotifierProvider<CodeProvider> ├── ChangeNotifierProvider<IssueProvider> └── ...

全局 Provider

MaterialApp之上通过MultiProvider注入:

classAtomGitAppextendsStatelessWidget{@overrideWidgetbuild(BuildContextcontext){returnMultiProvider(providers:[Provider<AtomGitApiClient>(create:(_)=>AtomGitApiClient(),),ChangeNotifierProvider<AuthProvider>(create:(_)=>AuthProvider(apiClient:/* 引用上面的 ApiClient */,)..tryRestoreSession(),),],child:MaterialApp(/* ... */),);}}
Provider类型生命周期用途
AtomGitApiClientProvider(不变)App 级别HTTP 客户端,被所有页面注入
AuthProviderChangeNotifierProviderApp 级别登录状态,驱动 Tab UI 切换

Provider<T>用于不变的服务对象。ChangeNotifierProvider<T>用于会变化、需要通知 UI 的状态。

页面级 Provider

每个详情页在 build 中创建自己的 Provider:

classRepoDetailScreenextendsStatelessWidget{@overrideWidgetbuild(BuildContextcontext){finalargs=ModalRoute.of(context)!.settings.argumentsasMap<String,dynamic>;returnChangeNotifierProvider(create:(_)=>RepoDetailProvider(context.read<AtomGitApiClient>())..load(args['owner'],args['name']),child:_RepoDetailBody(/* ... */),);}}

关键模式:create中完成两件事:

  1. 通过context.read<AtomGitApiClient>()获取全局 ApiClient
  2. 通过..load()级联语法立即触发数据加载

Provider 的生命周期与页面绑定:页面被 Navigator.pop 移除时,Provider 自动 dispose。

读取 Provider 的三种方式

context.read() — 一次性读取

// 在 create/onTap 等回调中,不需要监听finalapiClient=context.read<AtomGitApiClient>();provider.loadMore();

不会导致重建,适合事件处理函数内使用。

context.watch() — 持续监听

// 在 build 方法中,需要随状态变化重建finalisLoggedIn=context.watch<AuthProvider>().isLoggedIn;

每当 Provider 调用notifyListeners(),Widget 就会重建。适合 build 方法内使用。

Consumer — 局部监听

ChangeNotifierProvider.value(value:_userProvider!,child:Consumer<UserProvider>(builder:(context,provider,_){returnText('仓库:${provider.user?.publicRepos}');},),);

只有 Consumer 包裹的部分会重建,外层 Widget 不受影响。适合局部优化。

标准 Provider 模板

所有 Provider 遵循统一的加载模式:

classSomeProviderextendsChangeNotifier{finalAtomGitApiClient_apiClient;List<Item>_items=[];bool _isLoading=false;String?_error;bool _hasMore=false;int _page=1;// GettersList<Item>getitems=>List.unmodifiable(_items);boolgetisLoading=>_isLoading;String?geterror=>_error;boolgethasMore=>_hasMore;Future<void>load()async{_page=1;_isLoading=true;_error=null;notifyListeners();// ① 通知:开始加载try{finalresponse=await_apiClient.get(/* ... */);_items=/* parse response */;_hasMore=_items.length>=30;}onApiExceptioncatch(e){_error=e.message;// ② 区分 API 异常}catch(e){_error='加载失败';// ③ 兜底错误}finally{_isLoading=false;notifyListeners();// ④ 通知:加载完成}}}

四次notifyListeners()的节奏:

  1. 加载前:设置 loading 状态,UI 展示加载指示器
  2. 加载后(finally):清除 loading,UI 展示数据/错误

UI 状态模式

每个页面的 buildBody 方法遵循三态逻辑:

Widget_buildBody(SomeProviderprovider){// 优先级 1:错误(且无缓存数据)if(provider.error!=null&&provider.items.isEmpty){returnErrorRetryWidget(message:provider.error!,onRetry:()=>provider.load(),);}// 优先级 2:加载中if(provider.isLoading&&provider.items.isEmpty){returnconstLoadingIndicator(message:'加载中...');}// 优先级 3:空结果if(provider.items.isEmpty){returnconstCenter(child:Text('暂无数据'));}// 优先级 4:正常数据returnListView.builder(/* ... */);}

错误优先于加载中优先于空结果优先于正常数据 —— 这是判断链的顺序。

AuthProvider — 全局状态驱动

AuthProvider 是唯一贯穿全应用的状态:

classAuthProviderextendsChangeNotifier{finalAtomGitApiClient_apiClient;bool _isLoggedIn=false;boolgetisLoggedIn=>_isLoggedIn;Future<void>tryRestoreSession()async{finaltoken=awaitLocalStorage.instance.read<String>('access_token');if(token!=null&&token.isNotEmpty){_apiClient.setAccessToken(token);_isLoggedIn=true;notifyListeners();}}Future<void>setTokenFromManualInput(Stringtoken)async{_apiClient.setAccessToken(token);awaitLocalStorage.instance.write('access_token',token);_isLoggedIn=true;notifyListeners();}Future<void>logout()async{_apiClient.setAccessToken(null);awaitLocalStorage.instance.delete('access_token');_isLoggedIn=false;notifyListeners();}}

登录/登出后的连锁反应依赖 Provider 的广播机制:

AuthProvider.notifyListeners() → 所有 context.watch<AuthProvider>() 的 Widget 重建 → MainShell 底部导航切换显示 → ProfileTab 创建/销毁 UserProvider → HomeTab 切换数据源 → NotificationsTab 切换登录引导/占位

不需要手动通知各个组件,Provider 自动处理依赖传播。

changeNotifierProvider.value vs create

// 标准用法:Provider 由 ChangeNotifierProvider 创建和 disposeChangeNotifierProvider(create:(_)=>SomeProvider(),child:_Body(),)// value 用法:Provider 已存在(手动管理生命周期)ChangeNotifierProvider.value(value:existingProvider,child:Consumer<SomeProvider>(/* ... */),)

ProfileTab 使用.value的原因是它手动管理 UserProvider 的创建/销毁(跟随登录状态),不能交给create自动处理。

避免嵌套地狱

通过 Provider 的架构,UI 代码不直接持有数据加载逻辑:

// 不这样写:UI 中直接调 APIclass_BodyStateextendsState<_Body>{List<Repository>_repos=[];bool _loading=false;Future<void>_load()async{setState(()=>_loading=true);finalresp=awaithttp.get(/* ... */);setState((){_repos=/* ... */;_loading=false;});}}// 而是这样写:Provider 封装数据逻辑class_BodyStateextendsState<_Body>{@overrideWidgetbuild(BuildContextcontext){finalprovider=context.watch<RepoDetailProvider>();if(provider.isLoading)returnLoadingIndicator();returnListView(/* provider.repositories */);}}

Provider 将异步加载、错误处理、分页状态从 Widget 的 State 中剥离,Widget 只关心"当前应该展示什么"。

http://www.zskr.cn/news/1495499.html

相关文章:

  • 2026嘉兴AI搜索优化服务商实战选型评测与避坑指南全解析 - 品牌报告
  • 如何快速掌握MPV_lazy播放器:Windows用户的终极配置指南
  • Kinetis K22F I2S/SAI低功耗时序深度解析与音频系统设计指南
  • Path of Building终极指南:5分钟快速掌握流放之路最强Build规划工具
  • CAPL脚本里那些坑:为什么我的变量值总是不对?
  • 5个简单步骤掌握Trelby:免费专业剧本写作软件的完整指南
  • 从Dijkstra到A*:用动画和真实地图数据,彻底搞懂路径规划算法的演进与选型
  • Windows Terminal文件拖放终极指南:3个技巧让命令行效率翻倍
  • 影刀RPA新手教程_变量作用域与生命周期管理
  • 昇腾CANN集合通信库HCCL深度解析:分布式训练性能优化与多机多卡通信实战完整技术指南
  • McAfee Stinger Raptor(迈克菲杀毒软件
  • 企业级AI 知识引擎:01从0到1完整技术蓝图---视频
  • 嵌入式开发时序规范解析:从K60外设接口到PCB设计实战
  • 深圳露点仪厂家排行:多行业适配的专业选型参考 - 起跑123
  • CentOS7上OpenStack Queens版一键部署踩坑实录:从网卡改名到Dashboard访问
  • 小红书视频下载哪个工具好用?2026免费工具全面实测对比推荐 - 科技大爆炸
  • 如何在Windows上使用iperf3进行专业网络性能测试:完整指南
  • HIUI项目架构解析:Monorepo架构与组件化设计思想
  • 高分好文分享 | 内皮GABA调控血管稳态,云克隆助力主动脉夹层机制与诊断研究
  • 2026企业邮箱注册平台实力榜:六家国产服务商在安全加密与智能管理上的核心优势深度解析 - 品牌发掘
  • 掌握量化投资核心武器:JQData SDK的Alpha因子实战指南
  • 2026五大SEO优化公司评测:专业团队赋能企业流量精准高效增长 - GEO优化
  • 海外拍卖直播风控数据上报:跨境网络加密传输方案设计实践
  • 2026吴江钼酸钠专业订购商实力榜:六家本土高纯度供应商的核心技术优势深度解析 - 品牌发掘
  • Navicat Mac版无限试用期重置:3种强力方法实现永久免费使用
  • 从科研绘图到业务地图:如何用ArcGIS为你的坐标点数据快速匹配正确的地理坐标系(WGS-84/GCJ-02详解)
  • 小红书视频怎么无水印保存到手机?2026免费保存高清视频完整教程 - 科技大爆炸
  • 怎样轻松获取网盘直链:开源下载助手LinkSwift实战指南
  • 2026年 财务代账/代理记账公司推荐榜单:覆盖佛山/广州荔湾内资外资、高新企业及一般纳税人、小规模与零申报会计报税服务! - 品牌发掘
  • 从证伪主义到认知殖民:旧AI体系逻辑死亡的事实论证与贾子理论的范式意义