当前位置: 首页 > 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.jsqmd.com/news/983757/

相关文章:

  • Kinetis K22F I2S/SAI低功耗时序深度解析与音频系统设计指南
  • 2026嘉兴AI搜索优化服务商实战选型评测与避坑指南全解析 - 品牌报告
  • 义乌爪钻批发常见问题全面解答(2026最新版) - 信息热点
  • 2026东莞AI短视频怎么选?本土TOP8实测榜单,避坑推荐 - 信息热点
  • 如何快速掌握MPV_lazy播放器:Windows用户的终极配置指南
  • 告别龟速下载!LinkSwift网盘直链助手5分钟极速配置指南
  • Path of Building终极指南:5分钟快速掌握流放之路最强Build规划工具
  • CAPL脚本里那些坑:为什么我的变量值总是不对?
  • 2026应急发电车出租费用排行榜:六家高性价比本土品牌核心优势与报价深度解析 - 品牌发掘
  • Python多线程居然比单线程还慢?原来GIL坑在这
  • 从Dijkstra到A*:用动画和真实地图数据,彻底搞懂路径规划算法的演进与选型
  • HCS12指令集如何优化C语言编译:从寻址模式到循环控制
  • 10个必学的Windows 10终极瘦身技巧:免费开源工具完整指南
  • 抖音评论批量下载工具:5分钟获取完整评论数据的终极指南
  • 5个简单步骤掌握Trelby:免费专业剧本写作软件的完整指南
  • 目前最好的沉香品牌数据报告 - 信息热点
  • 嵌入式无线MCU设计实战:从数据手册时序参数到射频链路预算
  • 泰州全域闲置黄金、奢侈品变现实用指南|30年老店・精选本地连锁实体门店 - GrowthUME
  • 250款专业Xshell配色方案:重新定义您的终端视觉体验
  • Czkawka/Krokiet终极指南:10分钟掌握跨平台文件清理神器
  • 如何快速解密网易云音乐NCM格式:3步实现跨平台播放自由
  • Kinetis K22F I2S低功耗模式时序分析与嵌入式音频设计实战
  • 10分钟掌握Swift Express路由技巧:URL参数与请求处理实战
  • League-Toolkit深度评测:英雄联盟玩家的3大效率提升秘籍与实战指南
  • 3个步骤让Calibre重获豆瓣元数据:告别API限制的智能爬虫插件
  • 5分钟完成Windows系统优化:WinUtil终极指南
  • Windows Terminal文件拖放终极指南:3个技巧让命令行效率翻倍
  • 2026年二氧化碳捕集设备哪家好 行业深度解析与优质厂家推荐指南 - 信息热点
  • WinUtil技术架构深度剖析:模块化Windows系统管理工具的设计与实现
  • 深圳静电测试仪厂家排行:核心参数实测对比 - 起跑123