写点什么

拥抱 -Koin,放弃 -Dagger 吧!,android 开发技术难点

用户头像
Android架构
关注
发布于: 2021 年 11 月 03 日

每次编译之前我都会先 clean 然后才会 rebuild,我得到下面这个结果


Koin:BUILD SUCCESSFUL in 17s88 actionable tasks: 83 executed, 5 up-to-date


Dagger:BUILD SUCCESSFUL in 18s88 actionable tasks: 83 executed, 5 up-to-date


我认为这个结果证明了,如果是在一个更大、更真实的项目中,这个代价是非常昂贵。

1.3 使用对比

如果你想在 MVVM 和 Android Support lib 中使用 Dagger 你必须这么做。


首先在 module gradle 中 添加 Dagger 依赖。


kapt "com.google.dagger:dagger-compiler:dagger_version"implementation "com.google.dagger:dagger:$dagger_version"


然后创建完 modules 和 components 文件之后, 需要在 Application 中 初始化 Dagger(或者其他方式初始化 Dagger)。


Class MyApplication : Application(), HasActivityInjector {@Injectlateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>


override fun activityInjector() = dispatchingAndroidInjector


fun initDagger() {DaggerAppComponent.builder().application(this).build().inject(this)}}


所有的 Activity 继承 BaseActivity,我们需要实现 HasSupportFragmentInjector 和 inject DispatchingAndroidInjector。


对于 view models,我们需要在 BaseFragment 中注入 ViewModelFactory,并实现 Injectable。


但这并不是全部。还有更多的事情要做。


对于每一个 ViewModel、Fragment 和 Activity 我们需要告诉 DI 如何注入它们,正如你所见我们有 ActivityModule、FragmentModule、和 ?ViewModelModule。


我们来看一下下面的代码


@Moduleabstract class ActivityModule {@ContributesAndroidInjector(modules = [FragmentModule::class])abstract fun contributeMainActivity(): MainActivity


//Add your other activities here}


Fragments 如下所示:


@Moduleabstract class FragmentModule {@ContributesAndroidInjectorabstract fun contributeLoginFragment(): LoginFragment


@ContributesAndroidInjectorabstract fun contributeRegisterFragment(): RegisterFragment


@ContributesAndroidInjectorabstract fun contributeStartPageFragment(): StartPageFragment}


ViewModels 如下所以:


@Moduleabstract class ViewModelModule {


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


@Bindsabstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory


@Binds@IntoMap@ViewModelKey(loginViewModel::class)abstract fun bindLoginFragmentViewModel(loginViewModel: loginViewModel): ViewModel


@Binds@IntoMap@ViewModelKey(StartPageViewModel::class)abstract fun bindStartPageViewModel(startPageViewModel: StartPageViewModel): ViewModel......}


所以你必须在 DI modules 中添加这些 Fragments、Activities 和 ViewModels。


「那么在 Koin 中如何做」


你需要在 module gradle 中添加 Koin 依赖


implementation?"org.koin:koin-android-viewmodel:$koin_version"


然后我们需要创建 module 文件,稍后我告诉你怎么做,实际上我们并不需要像 Dagger 那么多文件。


「Dagger 还有其他问题」


学习 Dagger 成本是很高的,如果有人加入你的项目或者团队,他/她不得不花很多时间学习 Dagger,我使用 Dagger 两年了,到现在还不是很了解,每次我开始学习 Andorid 新技术的时候,我不得不去搜索和学习如何用 Dagger 实现新技术。


「来看一下 Koin 代码」


首先我们需要添加 Koin 依赖,如下所示:


implementation?"org.koin:koin-android-viewmodel:$koin_version"


我们使用的是 koin-android-viewmodel 库,因为我们希望在 MVVM 中使用它,当然还有其他的依赖库。


添加完依赖之后,我们来实现第一个 module 文件,像 Dagger 一样,可以在一个单独的文件中实现每个模块,但是由于代码简单,我决定在一个文件中实现所有模块,你也可以把它们分开。


首先我们需要了解一下 koin 语法特性


  • get():解析 Koin 模块中的实例,调用 get() 函数解析所请求组件需要的实例,这个 get() 函数通常用于构造函数中,注入构造函数值

  • factory:声明这是一个工厂组件,每次请求都为您提供一个新实例

  • single:采用单例设计模式

  • name:用于命名定义,当您希望具有不同类型的同一个类的多个实例时,需要使用它


我们没有创建具有多个注释和多个组件的许多文件,而是为 DI 注入每个类的时候,提供一个简单、可读的文件。


「了解完 koin 语法特性之后,我们来解释下面代码什么意思」


private?val?retrofit:?Retrofit?=?createNetworkClient()


createNetworkClient 方法创建 Retrofit 实例,设置 baseUrl,添加 ?ConverterFactory 和 Interceptor


private val generalApi: GeneralApi = retrofit.create(GeneralApi::class.java)private val authApi: AuthApi = retrofit.create(AuthApi::class.java)


AuthApi 和 GeneralApi 是 retrofit 接口


val viewModelModule = module {viewModel { LoginFragmentViewModel(get()) }viewModel { StartPageViewModel() }


}


在 module 文件中声明为 viewModel, Koin 将会向 ViewModelFactory 提供 viewModel,将其绑定到当前组件。


正如你所见,在 LoginFragmentViewModel 构造函数中有调用了 get() 方法,get() 会解析一个 LoginFragmentViewModel 需要的参数,然后传递给 LoginFragmentViewModel,这个参数就是 AuthRepo。


最后在 Application onCreate 方法中添加如下代码


startKoin(this, listOf(repositoryModule, networkModule, viewModelModule))


这里只是调用 startKoin 方法,传入一个上下文和一个希望用来初始化 Koin 的模块列表。


现在使用 ViewModel 比使用纯 ViewModel 更容易,在 Fragment 和 Activity 视图中添加下面的代码


private?val?startPageViewModel:?StartPageViewModel?by?viewModel()


通过这段代码,koin 为您创建了一个 StartPageViewModel 对象,现在你可以在 Fragment 和 Activity 中使用 view model

总结

总共从以下 4 个方面对比了 Dagger 和 Kotlin:


  • 文件数量:基于 mvvm 架构,分别使用了 Dagger 和 koltin 作为依赖注入框架,初始化 Dagger 时至少需要 9 个文件,而 koltin 只需要 2 个文件,Dagger 文件数量远超过 koltin

  • 代码行数:作者使用了 Statistic 工具,反复对比了项目编译前和编译后,Dagger 和 Koin 生成的代码行数,如下图所示



用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
拥抱-Koin,放弃-Dagger吧!,android开发技术难点