使用Koin来完成Kotlin的依赖注入

在以前使用MVP的同窗,若是你使用过依赖注入框架Dagger的话,你就会发现,它是多么的难用,这里对Dagger的使用就不作介绍了。咱们来一块儿学习在kotlin上的新的依赖注入框架koinjava

本文使用kotlin + Jetpackandroid

按照谷歌的建议,一个APP,应该包含UI层,ViewModel层,Repository层,这里简单介绍一下,UI持有ViewModel的引用,ViewModel持有Repository的引用,Repository持有数据库Dao层和网络Network层数据库

使用Koin

引入依赖:api

def retrofit_version = '2.6.0'
def moshiVersion = '1.8.0'
def koin_version = "2.0.1"
def viewmodel_ktx = '2.2.0-alpha03'
def kotlinCoroutineVersion = "1.0.1"

// retrofit以及moshi转换,将响应的结果解析成对象
implementation "com.squareup.retrofit2:retrofit:${retrofit_version}"
implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"

// moshi 解析JSON
implementation "com.squareup.moshi:moshi-kotlin:$moshiVersion"
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion"

// koin 依赖注入
implementation "org.koin:koin-android:$koin_version"
implementation "org.koin:koin-android-viewmodel:$koin_version"

// 可以使用协程并能够观察生命周期的ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$viewmodel_ktx"

// 协程
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutineVersion"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutineVersion"
    
    
复制代码

看完所须要的依赖,有的同窗可能会问,为何没有Retrofit的adapter,像implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'等,这里想介绍的是协程,Retrofit的2.6.0版本已经开始支持suspend函数了。bash

Koin的使用须要咱们在Application里面进行注册:网络

override fun onCreate() {
        super.onCreate()
        startKoin{
            androidLogger()
            androidContext(this@BaseApplication)
            modules(listOf(repoModule, viewmodelModule, networkModule))
        }
    }
复制代码

在Application里面,注册了三个module,分别对应的是咱们的仓库层,ViewModel层,网络层框架

新建文件夹di,咱们将三个module写在这里ide

// NetworkModule.kt
val api = ApiRepo.api
val networkModule = module {
    single {
        api
    }
}

// RepoModule.kt
val repoModule = module {
    single {
        MainRepo(get())
    }
}

// ViewModelModule.kt
val viewmodelModule = module {
    viewModel {
        MainViewModel(get())
    }
}
// ApiRepo.kt
object ApiRepo {
    private val okHttpClient = OkHttpClient.Builder()
        .build()

    private val retrofit = Retrofit.Builder()
        .client(okHttpClient)
        .baseUrl("your baseurl")
        .addConverterFactory(MoshiConverterFactory.create())
        .build()

    val api : Api = retrofit.create(Api::class.java)
}

// Api.kt
interface Api {
    @GET("")
    suspend fun getCountryData(): BaseModel<List<CountryModel>>
}

复制代码

上面的代码很简单,咱们每次新建的ViewModel,Repository以后,在viewmodelModule.kt和RepoModule.kt分别进行声明便可,咱们看到,声明ViewModel的时候使用的是MainViewModel(get()),这里多了个get(),为何?由于咱们的ViewModel层是要持有仓库层的引用的,使用get()的话,就会去在全部的注入的类里面去寻找咱们须要的,简单吧。函数

咱们看到在API里,咱们在调用接口的时候使用了suspend关键字,返回的结果也再也不是一个Call了,咱们在使用的时候只须要开一个协程,便可拿到咱们须要的数据,而后使用LiveData就能将数据发送到咱们的UI上学习

下面咱们看具体的代码:

// MainRepo.kt
class MainRepo(private val api:Api) {
    suspend fun getCountryData() : BaseModel<List<CountryModel>> = api.getCountryData()
}

// MainViewModel.kt
class MainViewModel(private val repo: MainRepo) : ViewModel() {

    var countryLiveData = MutableLiveData<BaseModel<List<CountryModel>>()
    fun getCountryData() {
    // 在Activity销毁的时候,这里会自动关闭
        viewModelScope.launch {
            countryLiveData.value = fetch(repo.getCountryData())
        }
    }
}


class MainActivity : AppCompatActivity() {
    
    // 只须要经过koin的by viewModel就能够拿到咱们注册的MainViewModel了
    private val mainViewModel by viewModel<MainViewModel>()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        mainViewModel.getCountryData()
        mainViewModel.countryLiveData.observe(this, Observer {
            // do something
        })
        
    }
}
复制代码

总结

  • 使用了koin,在业务复杂的时候就方便了许多,不再用经过构造函数传来传去了

  • Retrofit的2.6.0版本已经默认支持协程了,可能有些同窗会以为,就使用一个suspend的话,有些异常该怎么处理,其实咱们在ViewModel层,在调用仓库层的方法的时候,可使用一个try-catch便可去处理异常了,或者来一个BaseViewModel,统一处理

  • 使用LiveData + ViewModel + coroutines,在请求网络的时候就不用担忧切换线程啦,页面销毁时如何取消请求啦等问题了,固然,ViewModel要使用上面gradle里面依赖的ViewModel

相关文章
相关标签/搜索