鸿蒙Flutter 依赖注入模式:使用Provider管理服务类 一、依赖注入概述依赖注入Dependency Injection简称DI是一种软件设计模式用于实现控制反转Inversion of Control简称IoC。在Flutter开发中依赖注入可以帮助我们解耦组件组件不直接创建依赖降低耦合度提高可测试性方便替换为mock对象进行测试简化维护集中管理依赖易于维护和替换实现复用同一个服务可以在多个组件中复用Provider不仅可以用于状态管理还可以作为依赖注入容器管理服务类的生命周期。二、创建服务类在使用Provider进行依赖注入之前我们需要先创建服务类。服务类通常是无状态的工具类提供特定的功能。2.1 日志服务classLogService{voidinfo(Stringmessage){debugPrint([INFO]$message);}voiderror(Stringmessage,[Object?error]){debugPrint([ERROR]$message:$error);}}2.2 存储服务classStorageService{String_data;FuturevoidsaveData(Stringdata)async{awaitFuture.delayed(constDuration(milliseconds:100));_datadata;}FutureStringloadData()async{awaitFuture.delayed(constDuration(milliseconds:100));return_data;}}2.3 API服务classApiService{FutureMapString,dynamicfetchProduct(Stringid)async{awaitFuture.delayed(constDuration(seconds:1));return{id:id,name:商品$id,price:99.9,};}}三、使用Provider注入服务使用Provider注入服务非常简单只需要在MultiProvider中声明即可MultiProvider(providers:[ProviderLogService(create:(_)LogService()),ProviderStorageService(create:(_)StorageService()),ProviderApiService(create:(_)ApiService()),ChangeNotifierProvider(create:(context)DataProvider(logService:context.readLogService(),storageService:context.readStorageService(),),),],child:constMyApp(),)3.1 注入不可变服务对于无状态的服务类使用Provider即可ProviderLogService(create:(_)LogService())3.2 注入可变状态对于需要管理状态的类使用ChangeNotifierProviderChangeNotifierProvider(create:(context)DataProvider(logService:context.readLogService(),storageService:context.readStorageService(),),)四、在Provider中使用依赖在ChangeNotifier中使用依赖注入的服务classDataProviderextendsChangeNotifier{finalLogService_logService;finalStorageService_storageService;String_data初始数据;DataProvider({requiredLogServicelogService,requiredStorageServicestorageService,}):_logServicelogService,_storageServicestorageService;Stringgetdata_data;FuturevoidupdateData(StringnewData)async{_logService.info(更新数据:$newData);_datanewData;await_storageService.saveData(newData);notifyListeners();}FuturevoidloadData()async{_logService.info(加载数据);_dataawait_storageService.loadData();notifyListeners();}}五、在Widget中使用服务在Widget中使用依赖注入的服务5.1 获取服务classProductDetailPageextendsStatelessWidget{constProductDetailPage({super.key});overrideWidgetbuild(BuildContextcontext){finallogServicecontext.readLogService();returnScaffold(appBar:AppBar(title:constText(商品详情)),body:Center(child:ElevatedButton(onPressed:(){logService.info(用户点击加入购物车);context.readCartProvider().addItem(1,商品,19.9);},child:constText(加入购物车),),),);}}5.2 注意事项使用context.readT()获取不需要监听的服务使用context.watchT()获取需要监听变化的状态服务必须在当前Provider之前声明依赖注入的服务默认是单例六、单例服务与工厂模式6.1 Provider默认创建单例Provider默认创建单例实例整个应用中只创建一次MultiProvider(providers:[Provider(create:(_)ApiService()),],child:constMyApp(),)6.2 使用Provider.value如果需要传入已存在的实例可以使用Provider.valuefinalapiServiceApiService();MultiProvider(providers:[Provider.value(value:apiService),],child:constMyApp(),)6.3 延迟初始化使用ProxyProvider进行延迟初始化只有在需要时才创建ProviderMultiProvider(providers:[Provider(create:(_)ApiService()),ChangeNotifierProxyProviderApiService,CartProvider(create:(context)CartProvider(apiService:context.read()),update:(context,apiService,cartProvider){returncartProvider!..updateApiService(apiService);},),],child:constMyApp(),)七、依赖注入的优势优势说明解耦组件不直接创建依赖降低耦合可测试方便替换为mock对象进行测试可维护集中管理依赖易于维护可复用同一个服务可以在多个组件中复用生命周期管理Provider自动管理服务生命周期八、最佳实践8.1 将服务类与状态类分离服务类应该是无状态的工具类状态类应该只负责管理状态// 服务类 - 无状态classApiService{FutureUserfetchUser(Stringid)async{...}}// 状态类 - 管理状态classUserProviderextendsChangeNotifier{finalApiService_apiService;User?_user;UserProvider({requiredApiServiceapiService}):_apiServiceapiService;}8.2 使用Provider注入不可变服务对于无状态的服务使用Provider而不是ChangeNotifierProviderProviderLogService(create:(_)LogService())8.3 使用ChangeNotifierProvider管理可变状态对于需要管理状态的类使用ChangeNotifierProviderChangeNotifierProvider(create:(_)CartProvider())8.4 按依赖顺序声明Provider依赖其他Provider的Provider必须在被依赖的Provider之后声明MultiProvider(providers:[ProviderApiService(create:(_)ApiService()),// CartProvider依赖ApiService必须在ApiService之后ChangeNotifierProvider(create:(context)CartProvider(apiService:context.read()),),],child:constMyApp(),)8.5 在构造函数中注入依赖不要在方法中直接使用context.read而是在构造函数中注入依赖classCartProviderextendsChangeNotifier{finalApiService_apiService;// 正确在构造函数中注入CartProvider({requiredApiServiceapiService}):_apiServiceapiService;voidfetchProducts(){// 使用注入的依赖_apiService.fetchProducts();}}九、代码示例9.1 创建一个依赖注入演示页面classDependencyInjectionPageextendsStatelessWidget{constDependencyInjectionPage({super.key});overrideWidgetbuild(BuildContextcontext){returnMultiProvider(providers:[ProviderLogService(create:(_)LogService()),ProviderStorageService(create:(_)StorageService()),ChangeNotifierProvider(create:(context)DataProvider(logService:context.readLogService(),storageService:context.readStorageService(),),),],child:Scaffold(appBar:AppBar(title:constText(依赖注入模式演示)),body:ListView(padding:constEdgeInsets.all(16),children:[_buildSection(服务类定义,_serviceDefinition()),_buildSection(依赖注入演示,_diDemo()),_buildSection(在Provider中使用依赖,_providerWithDependencies()),_buildSection(依赖注入优势,_diAdvantages()),],),),);}Widget_buildSection(Stringtitle,Widgetcontent){returnCard(margin:constEdgeInsets.only(bottom:16),child:Padding(padding:constEdgeInsets.all(16),child:Column(crossAxisAlignment:CrossAxisAlignment.start,children:[Text(title,style:constTextStyle(fontSize:18,fontWeight:FontWeight.bold)),constSizedBox(height:12),content,],),),);}Widget_diDemo(){returnColumn(children:[ConsumerDataProvider(builder:(context,provider,child){returnText(当前数据:${provider.data},style:constTextStyle(fontSize:18),);},),constSizedBox(height:16),TextField(decoration:constInputDecoration(labelText:输入新数据),onSubmitted:(value){context.readDataProvider().updateData(value);},),constSizedBox(height:16),ElevatedButton(onPressed:()context.readDataProvider().updateData(Hello DI!),child:constText(设置Hello),),],);}}9.2 代码解析在这个演示页面中服务类定义展示了LogService、StorageService等服务类的定义方式依赖注入演示展示了如何使用MultiProvider注入多个服务在Provider中使用依赖展示了如何在DataProvider中使用注入的服务依赖注入优势总结了依赖注入的优势十、关键要点10.1 Provider可作为依赖注入容器使用Provider不仅可以管理状态还可以管理服务类的生命周期。10.2 使用Provider注入不可变服务对于无状态的服务类使用Provider即可不需要使用ChangeNotifierProvider。10.3 Provider默认创建单例实例Provider默认创建单例实例整个应用中只创建一次。10.4 服务之间可以有依赖关系一个Provider可以依赖其他Provider但必须按依赖顺序声明。10.5 便于测试和维护使用依赖注入可以方便地替换为mock对象进行测试同时也便于维护和扩展。十一、总结依赖注入是一种重要的软件设计模式可以帮助我们解耦组件、提高可测试性和可维护性。在Flutter中Provider不仅可以用于状态管理还可以作为依赖注入容器使用。在实际开发中建议遵循以下原则将服务类与状态类分离使用Provider注入不可变服务使用ChangeNotifierProvider管理可变状态按依赖顺序声明Provider在构造函数中注入依赖不要直接使用context.read希望本文能帮助你掌握依赖注入模式的使用并在实际项目中正确应用

相关新闻

相关新闻

企业招聘管理系统JAVA源代码+数据库,实现公司职位发布,简历投递,招聘管理,开箱就能用的项目-BOSS直聘源码

企业招聘管理系统JAVA源代码+数据库,实现公司职位发布,简历投递,招聘管理,开箱就能用的项目-BOSS直聘源码

博主介绍: 所有项目都配有从入门到精通的安装教程,可二开,提供核心代码讲解,项目指导。 项目配有对应开发文档、解析等 项目都录了发布和功能操作演示视频;项目的界面和功能都可以定制,包安装运行&#xff…

2026/10/6 11:21:21
【小程序课程设计/毕业设计】校园专业信息聚合与科普小程序的设计与实现 智慧校园专业报考解读服务管理系统【附源码、数据库、万字文档】

【小程序课程设计/毕业设计】校园专业信息聚合与科普小程序的设计与实现 智慧校园专业报考解读服务管理系统【附源码、数据库、万字文档】

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/9/29 6:45:58
小程序毕设项目:基于小程序的个性化健康生活指导平台 居民健康生活习惯监督与管理小程序 轻量化智慧健康生活服务管理系统 (源码+文档,讲解、调试运行,定制等)

小程序毕设项目:基于小程序的个性化健康生活指导平台 居民健康生活习惯监督与管理小程序 轻量化智慧健康生活服务管理系统 (源码+文档,讲解、调试运行,定制等)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/9/29 12:15:47

最新新闻

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现 【免费下载链接】serenity The Serenity Operating System 🐞 项目地址: https://gitcode.com/GitHub_Trending/se/serenity 导读 本文以 getopt(3) 手册 为核心&a…

2026/10/5 3:18:56
轻量服务器还是ECS?大促云服务器选购与避坑实战指南

轻量服务器还是ECS?大促云服务器选购与避坑实战指南

每年大促节点,群里永远有人在问同一个问题:“38元的轻量服务器到底怎么抢?为什么我每次点进去都是已售罄?68元直购和99元的ECS我到底选哪个?”作为一个常年帮团队和自己采购云服务器的老用户,我太清楚这种纠…

2026/10/5 3:42:18
为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南 【免费下载链接】agents Multi-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity 项目地址:…

2026/10/5 19:39:38
PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署 【免费下载链接】PaddleOCR Turn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between i…

2026/10/5 16:06:34
Spring源码解析:构造器注入的类型转换与候选匹配机制

Spring源码解析:构造器注入的类型转换与候选匹配机制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 5:51:09
openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由 【免费下载链接】openai-agents-python A lightweight, powerful framework for multi-agent workflows 项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-pyth…

2026/10/5 5:40:36

日新闻

周新闻

月新闻