Flutter for OpenHarmony:kiwi 极简依赖注入容器,解耦神器(减少样板代码的 DI 库) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:kiwi 极简依赖注入容器,解耦神器(减少样板代码的 DI 库) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net

在这里插入图片描述

前言

在构建大型 Flutter 应用时,依赖注入 (Dependency Injection, DI) 是绕不开的话题。

  • ViewModel 依赖 Service。
  • Service 依赖 Repository。
  • Repository 依赖 HttpClient 和 Database。

如果全靠手动 new 和传参,代码会变成一团乱麻(Dependency Hell)。

Flutter 社区有很多 DI 解决方案,如 Provider, GetIt, Riverpod。而 Kiwi 是一个非常轻量级且强大的选择。它最大的特点是支持 代码生成 (Code Generation),这大大减少了手写注册代码的工作量,并且在编译时就能发现依赖错误,而不是等到运行时崩给你看。

对于 OpenHarmony 应用,Kiwi 的纯 Dart 特性使其能够无缝运行,帮助我们将业务逻辑与 UI、原生实现解耦。

一、核心概念:IoC 容器

Kiwi 的核心是一个 IoC (Inversion of Control) 容器。你把所有的工具类、服务类都扔进这个容器里,需要用的时候找容器要。

它支持两种生命周期:

  1. Factory (工厂模式): 每次请求都创建一个新的实例。
  2. Singleton (单例模式): 整个 App 生命周期只创建一次,后续请求返回同一个实例。

请求实例

检查类型

工厂模式

单例模式

Flutter App

Kiwi 容器

注册表

新实例

缓存实例

二、集成与基础用法

2.1 添加依赖

Kiwi 分为运行时核心库和编译时生成器。

dependencies:kiwi: ^5.0.1 dev_dependencies:build_runner: ^2.4.0 kiwi_generator: ^5.0.1 

2.2 定义注入器 (Injector)

我们需要定义一个抽象类(或接口)来描述“如何注册依赖”。

// injector.dartimport'package:kiwi/kiwi.dart';abstractclassInjector{// 定义一个 setup 方法,用于注册所有依赖voidsetup();// 也可以定义获取实例的 helper 方法staticfinalKiwiContainer container =KiwiContainer();staticvoid resolve<T>()=> container.resolve<T>();}

2.3 使用注解自动生成代码

这是 Kiwi 的精髓。使用 @Register.factory@Register.singleton 注解。

// injector.dartimport'package:kiwi/kiwi.dart';import'services/user_service.dart';import'services/api_client.dart';part'injector.g.dart';// 这一行很重要!abstractclassInjector{@Register.singleton(ApiClient)@Register.factory(UserService)voidsetup();}class $InjectorextendsInjector{// 这个方法会被生成代码覆盖@overridevoidsetup(){// 自动生成的代码会放在这里 _$Injector().setup();}}// 对应的 Service 类classApiClient{ApiClient();}classUserService{finalApiClient client;// Kiwi 会自动分析构造函数,把 container 中的 ApiClient 注入进来UserService(this.client);}

运行生成命令:

dart run build_runner build 

生成后的 injector.g.dart 会自动处理依赖关系:UserService 需要 ApiClient,Kiwi 会自动先解析 ApiClient 并传给 UserService

在这里插入图片描述

2.4 初始化与调用

main.dart 中:

voidmain(){// 1. 初始化容器var injector = _$Injector(); injector.setup();// 2. 获取实例var userService =KiwiContainer().resolve<UserService>();runApp(MyApp());}
在这里插入图片描述

三、OpenHarmony 适配与实战:平台差异化注入

在鸿蒙开发中,我们经常遇到这种情况:

  • 在 Android/iOS 上,使用 plugins_a
  • 在 OpenHarmony 上,因为插件暂不支持,我们需要自己写一个简易版的 Dart 实现,或者调用鸿蒙原生 MethodChannel。

Kiwi 可以通过 命名构造函数子类 完美解决这个问题。

3.1 场景:文件存储服务

假设我们有一个 StorageService

abstractclassStorageService{Future<void>save(String key,String value);}classMobileStorageServiceimplementsStorageService{@overrideFuture<void>save(String key,String value){print('使用标准移动端存储');// ...returnFuture.value();}}classOhosStorageServiceimplementsStorageService{@overrideFuture<void>save(String key,String value){print('使用 OpenHarmony 专属沙箱存储');// ... 调用 path_provider 获取 el2 加密区returnFuture.value();}}

3.2 根据平台注册 (Conditional Registration)

虽然 Kiwi 的注解是在编译时运行的(无法知道运行时平台),但我们可以在 setup 方法中加入逻辑判断。

注意:kiwi_generator 目前主要做静态分析。对于动态逻辑,混合使用 手动注册 是最佳实践。

import'dart:io';// 用于 Platform.isFuchsia 等判断import'package:kiwi/kiwi.dart';classAppInjector{voidsetup(){final container =KiwiContainer();// 1. 生成部分(通用依赖) _$SharedInjector().setup();// 2. 手动部分(平台特定依赖)// 注意:OpenHarmony 的 dart:io Platform 检测可能还在完善中// 实际项目中建议结合 device_info_plus 或自定义 flagif(Platform.operatingSystem =='ohos'||Platform.isFuchsia){// 假设 ohos 标识 container.registerFactory<StorageService>((c)=>OhosStorageService());}else{ container.registerFactory<StorageService>((c)=>MobileStorageService());}}}// 通用的部分依然用 generatingabstractclassSharedInjector{@Register.singleton(ApiClient)voidsetup();}

这样,当你的 App 跑在鸿蒙设备上时,UI 获取到的 StorageService 自动就是 OhosStorageService,业务层代码完全不需要改动。

在这里插入图片描述

四、进阶技巧

4.1 命名实例 (Named Instances)

有时候你需要同一个类的两个不同实例(例如:两个 HttpClient,一个连内网,一个连外网)。

@Register.singleton(HttpClient, name:'internal')@Register.singleton(HttpClient, name:'external')voidsetup();// 获取var client = container.resolve<HttpClient>('internal');

4.2 模块化 (Modules)

不要把所有依赖都写在一个 Injector 类里。可以按功能模块拆分:

  • UserInjector
  • ProductInjector
  • CartInjector

然后在 main 中依次调用它们的 setup

4.3 配合 Flutter Bloc

Kiwi 和 Bloc 是绝配。

// 在 Bloc 初始化时注入 ServiceclassUserBlocextendsBloc<UserEvent,UserState>{finalUserService _service;// 默认构造函数让 Kiwi 自动注入UserBloc(this._service):super(InitialState());}// 注册 [email protected](UserBloc)voidsetup();// 在 UI 中使用BlocProvider( create:(context)=>KiwiContainer().resolve<UserBloc>(), child:UserPage(),);

五、总结

Kiwi 是一个显得“大巧不工”的库。它没有复杂的 Context 依赖(像 Provider),也没有全局的状态污染。它只是单纯地做好 对象创建与管理 这一件事。

对于 OpenHarmony 开发者,Kiwi 是实现 架构整洁 (Clean Architecture) 的有力帮手。它帮助我们将鸿蒙特有的底层实现(如基于 arkui plugin 的实现)隔离在 DI 层,保证上层 Dart 业务逻辑的纯粹性与可移植性。

最佳实践

  1. 构造函数注入:尽量使用构造函数参数来声明依赖,利用 Kiwi 的自动解析能力。
  2. 区分 Factory 与 Singleton:无状态的服务(Service/Repo)用 Singleton,有状态的对象(Bloc/ViewModel)用 Factory。
  3. 重新生成:每次修改了依赖关系,记得重新运行 build_runner

六、完整实战示例

import'package:kiwi/kiwi.dart';// === 业务类定义 ===abstractclassApiService{voidfetch();}classRealApiServiceextendsApiService{@overridevoidfetch()=>print('Calling Real API...');}abstractclassRepository{voidgetData();}classDataRepositoryextendsRepository{finalApiService api;DataRepository(this.api);// 依赖注入点@overridevoidgetData(){print('Repo getting data...'); api.fetch();}}// === 注入器定义 ===abstractclassInjector{// 标记这是一个 Singleton,且 Kiwi 会自动递归解析其依赖 (ApiService)@Register.singleton(Repository, from:DataRepository)@Register.singleton(ApiService, from:RealApiService)voidconfigure();}// === 生成的代码部分 (通常在 .g.dart 中,这里手动模拟) ===class _$InjectorextendsInjector{@overridevoidconfigure(){final container =KiwiContainer(); container.registerSingleton((c)=>RealApiService());// 自动注入 ApiService container.registerSingleton((c)=>DataRepository(c.resolve<ApiService>()));}}voidmain(){// 1. 初始化 (App启动时)var injector = _$Injector(); injector.configure();// 2. 使用 (通常在 Provider 或 Bloc 初始化时)var repo =KiwiContainer().resolve<Repository>(); repo.getData();// Output: // Repo getting data...// Calling Real API...}
在这里插入图片描述

Read more

当OpenClaw引爆全网,谁来解决企业AI Agent的“落地焦虑”?

当OpenClaw引爆全网,谁来解决企业AI Agent的“落地焦虑”?

2026 年 3 月,开源 AI Agent 框架 OpenClaw 在 GitHub 上的星标突破28万,并一度超越 React,成为 GitHub 最受关注的软件项目之一。短时间内,开发者利用它构建了大量实验性应用:从全栈开发辅助,到自动化营销脚本,再到桌面操作自动化,AI Agent 的能力边界正在迅速被拓展。 这股热潮也带动了另一个趋势——本地部署与算力硬件需求的快速增长。越来越多开发者尝试在个人设备或企业服务器上运行 Agent 系统,以获得更高的控制权和数据安全性。 从表面上看,AI Agent 似乎正从“概念验证”走向更广泛的开发实践。但在企业环境中,情况却没有想象中乐观。当企业负责人开始追问—— “它能直接解决我的业务问题吗?” 很多演示级产品仍难以给出令人满意的答案。 如何让 Agent 真正融入企业既有系统、适配复杂业务流程,正成为大模型产业落地必须跨越的一道门槛。 与此同时,中国不同城市的产业结构差异明显:互联网、

By Ne0inhk
二手平台出现OpenClaw卸载服务,299元可上门“帮卸”;2026年春招AI人才身价暴涨:平均月薪超6万;Meta辟谣亚历山大·王离职 | 极客头条

二手平台出现OpenClaw卸载服务,299元可上门“帮卸”;2026年春招AI人才身价暴涨:平均月薪超6万;Meta辟谣亚历山大·王离职 | 极客头条

「极客头条」—— 技术人员的新闻圈! ZEEKLOG 的读者朋友们好,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧。(投稿或寻求报道:[email protected]) 整理 | 苏宓 出品 | ZEEKLOG(ID:ZEEKLOGnews) 一分钟速览新闻点! * 微信员工辟谣“小龙虾可自动发红包”:不要以讹传讹 * 蚂蚁集团启动春招,超 70% 为 AI 相关岗位 * 受贿 208 万!拼多多一员工被抓 * 2026 年春招 AI 人才身价暴涨: 平均月薪超 6 万元 * 二手平台出现 OpenClaw 上门卸载服务 * 权限太高,国家互联网应急中心发布 OpenClaw 安全应用的风险提示 * 字节豆包内测 AI 电商功能:无需跳转抖音,日活用户数超

By Ne0inhk
遭“美国政府封杀”后,Anthropic正式提起诉讼!

遭“美国政府封杀”后,Anthropic正式提起诉讼!

整理 | 苏宓 出品 | ZEEKLOG(ID:ZEEKLOGnews) 据路透社报道,当地时间周一,AI 初创公司 Anthropic 正式对美国国防部及特朗普政府提起诉讼,抗议五角大楼将其列为“国家安全供应链风险”主体的决定。 Anthropic 在向美国加州北区地方法院提交的诉讼文件中表示,这一认定“史无前例且非法”,已对公司造成“不可挽回的损害”。公司希望法院撤销该决定,并指示联邦机构停止执行相关认定。 划定 AI 应用红线,双方观点不一 正如我们此前报道,这场争端的核心在于 Anthropic 为其核心 AI 模型 Claude 设定的两条技术使用红线,与美国国防部的使用需求发生根本冲突。 此前,Anthropic 曾与五角大楼签署一份价值最高可达 2 亿美元的合作合同,Claude 也成为少数被纳入美国机密网络环境进行测试的 AI 系统之一。 对此,Anthropic 一直坚持两条底线: * Claude 等技术不得被用于对美国民众的大规模国内监控;

By Ne0inhk
星标超 28 万,OpenClaw 两天两次大更!适配GPT 5.4,告别“抽卡式 Prompt”

星标超 28 万,OpenClaw 两天两次大更!适配GPT 5.4,告别“抽卡式 Prompt”

整理 | 梦依丹 出品 | ZEEKLOG(ID:ZEEKLOGnews) “We don’t do small releases.” 这是 OpenClaw 在发布 2026.3.7 版本时写下的一句话。 刚刚过去的周六与周日,这个 GitHub 星标已超 28 万 的 AI Agent 开源项目再次迎来两轮重量级更新。 两天两次更新:OpenClaw 做了一次“真正的大版本升级” 打开 OpenClaw 的 GitHub 更新日志,你会发现这次版本更新的规模确实不小。在 3 月 7 日发布更新后,第二天又迅速推出 2026.3.8-beta.1 和

By Ne0inhk