Koin 开发者炸了!7 条规则根治运行时错误,自动扫描太香了
编译零警告测试全绿上线直接炸。用过 Koin 的人或多或少都经历过这种场景——NoBeanDefFoundException在某个不起眼的页面突然蹦出来而你根本不知道是哪个依赖没注册。这不是 Bug是 Koin 的特性。它的运行时解析机制意味着编译器永远不会替你检查依赖图是否完整。但更多时候问题不在 Koin 本身而在于我们用错了。错题集先来看看项目中最常见的几种写法问题。永远用构造函数注入这是最重要的一条没有之一。// 错误写法 ❌ class UserRepository:KoinComponent{private val db: AppDatabase by inject()private val api: UserApi by inject()}看起来很简洁对吧但这其实是Service Locator 反模式不是依赖注入。依赖被隐藏外部看到UserRepository()完全不知道它依赖了什么。测试必须启动 Koinmock 一个依赖还得先startKoin测完还得stopKoin。运行时炸弹by inject()是 lazy 的如果 scope 已关闭才触发直接崩。// 正确写法 ✅ class UserRepository(private val db: AppDatabase, private val api: UserApi,){fun getUser(id: String)api.fetchUser(id)}val dataModulemodule{single{UserRepository(dbget(), apiget())}}依赖一目了然测试直接传 mock和 Koin 零耦合。规则业务类Repository、UseCase、DataSource永远不该实现KoinComponent。只有 Activity、Fragment 这种你无法控制构造函数的框架入口点才可以用。这种写法在我们项目中特别多也是扫描出来数量最大的一类问题。UseCase / Mapper 不要用 single// 错误写法 ❌ val domainModulemodule{single{GetUserUseCase(get())}single{UserMapper(get())}}UseCase 和 Mapper 本质上是无状态对象。用single注册意味着全局共享同一个实例。一旦哪天某个 UseCase 内部加了一个临时变量存中间结果所有调用方就共享了这份可变状态。并发场景下这种 Bug 极难复现、极难排查。// 正确写法 ✅ val domainModulemodule{factory{GetUserUseCase(get())}factory{UserMapper(get())}}factory每次注入都创建新实例用机制兜底彻底消除共享状态风险。ViewModel 必须用 viewModel { } 注册// 错误写法 ❌ single{UserProfileViewModel(get())}// 正确写法 ✅ viewModel{UserProfileViewModel(get())}用single注册 ViewModel 会导致三个严重问题内存泄漏永远不被回收、状态残留页面退出再进入看到旧数据、脱离生命周期管理。viewModel { }会将 ViewModel 绑定到对应的 ViewModelStoreOwner页面销毁时自动清理。面向接口注入// 错误写法 ❌ class UserRepositoryImpl(private val api: UserApiImpl, // 具体实现类):UserRepository // 正确写法 ✅ class UserRepositoryImpl(private val api: UserApi, // 接口):UserRepository val dataModulemodule{singleUserApi{UserApiImpl(get())}singleUserRepository{UserRepositoryImpl(get())}}规则single接口 { 实现类() }构造函数参数类型永远是接口。测试时替换实现只需改 Module业务代码零改动。同类型多实例必须用 named// 错误写法 ❌ —— 后者会静默覆盖前者 single{OkHttpClient.Builder().addInterceptor(authInterceptor).build()}single{OkHttpClient.Builder().addInterceptor(logInterceptor).build()}// 正确写法 ✅ single(named(auth)){OkHttpClient.Builder().addInterceptor(authInterceptor).build()}single(named(logging)){OkHttpClient.Builder().addInterceptor(logInterceptor).build()}Koin 发现同一类型注册了两次后者会静默覆盖前者没有任何警告。你以为注入的是带 Auth 的 Client实际拿到的是只有 Log 的那个。Compose Preview 中不能用 koinInject// 错误写法 ❌ Preview Composable funProductCardPreview(){val viewModel: ProductViewModelkoinViewModel()// 直接崩溃 ProductCard(viewModel.state)}// 正确写法 ✅ Preview Composable funProductCardPreview(){ProductCard(stateProductState(name示例商品, price99.0))}Android Studio 的 Preview 渲染器没有 Koin 运行环境调用koinViewModel()或koinInject()会直接崩溃。原则koinViewModel()只在 Screen 级别使用子组件只接收数据参数。七条规则汇总梳理下来一共整理了 7 条规则分为必须修改和建议修改两个级别|规则|检测内容|级别|| — | — | — ||KL001|业务类实现 KoinComponent|必须修改||KL002|非框架类中 by inject()|必须修改||KL003|ViewModel 用 single 注册|必须修改||KL004|Preview 中用 koinInject/koinViewModel|必须修改||KL005|UseCase/Mapper 用 single 注册|建议修改||KL006|构造函数参数使用 Impl 类型|建议修改||KL007|同类型多次注册无 named|建议修改|这里的必须修改和建议修改只是相对的。我们认为未来因为更换框架等原因产生影响更严重的为必须修改并非指实际业务上要立即更改。写在最后Koin 是一个好框架但好用和用好之间差着一个错题集的距离。编译器帮不了你但工具可以你可以将上述规则整理成skill让AI帮你自动诊断。你们项目中 Koin 的使用规范吗踩过哪些坑评论区聊聊。[#Android开发](javascript: [#Koin](javascript: [#依赖注入](javascript: [#代码规范](javascript: [#AndroidStudio插件](javascript:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2569416.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!