Retrofit 2.6之后的版本本身支持了使用Kotlin的協(xié)程镊折。使用起來更加簡潔横浑。
在2.6之前的版本中如果要使用協(xié)程可以添加coroutines-adapter來使用儡司。例如JakeWharton大神編寫的retrofit2-kotlin-coroutines-adapter
可以看到該項目已經(jīng)標(biāo)識為DEPRECATED嘉竟。推薦升級到2.6之后的版本
2.6版本之前的寫法
接口聲明
@GET("test")
fun test() : Deferred<TestResponse>
添加adapter
Retrofit.Builder()
.baseUrl(NetworkConfig.baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory.create())
.build()
調(diào)用:
GlobalScope.launch(Dispatchers.IO){
val response = test().await()
....
}
2.6版本之后
2.6版本之后不再需要設(shè)置Adapter睦柴,直接使用Retrofit自身的方式
接口聲明
@GET("test")
suspend fun test() : Response<TestResponse>
// 或者
@GET("test")
suspend fun test() : Call<TestResponse>
調(diào)用
GlobalScope.launch(Dispatchers.IO){
try{
val response = test()
if(response.isSuccessful){
...
}else{
...
}
}catch(e: Throwable){
...
}
}
//Call
GlobalScope.launch(Dispatchers.IO){
test().enqueue(object : Callback<TestResponse>{
override fun onFailure(call: Call<TestResponse>, t: Throwable) {
...
}
override fun onResponse(call: Call<TestResponse>, response: Response<TestResponse>){
...
}
}
}
使用協(xié)程最大的好處就是可以避免回調(diào)诽凌,使異步邏輯更加簡潔,清晰坦敌。以上的寫法已經(jīng)比RxJava或其他版本要直觀了侣诵。
如果你使用了官方的MVVM架構(gòu)痢法,并且升級到了Android X,可以更加簡潔杜顺。
添加Kotlin擴(kuò)展依賴
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0-beta01'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-beta01'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0-beta01'
接口聲明可以更直接
suspend fun test() : TestResponse
調(diào)用接口直接轉(zhuǎn)LiveData
val liveData: LiveData<TestResponse> = liveData{
val response = test()
emit(response)
}
這樣這個LiveData就直接把接口返回的數(shù)據(jù)給接受了财搁。
狀態(tài)處理
val liveData: LiveData<TestResponse> = liveData{
emit(State.Loading)
try {
val data = test()
emit(State.Success(data))
}catch (e: Exception){
emit(State.Error(e))
}
}
ViewModelScope
ViewmModel也添加了一個擴(kuò)展ViewModelScope
viewModelScope.launch {
val data = test()
...
}
LifecycleScope
LifecycleScope是lifecycleOwner的一個擴(kuò)展。
class TestFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
val data = test()
...
}
}
}
LifecycleScope中可以指定執(zhí)行的生命周期節(jié)點(diǎn)
lifecycleScope.launch {
//在Activity onStart之后執(zhí)行
whenStarted {
val data = test()
...
}
}
LiveDataScope, ViewModelScope和lifecycleScope會自動處理自身的生命周期躬络,在生命周期結(jié)束時會自動取消沒有執(zhí)行完成的協(xié)程任務(wù)尖奔,但是使用lifecycleScope應(yīng)該注意,因?yàn)閘ifecycleScope可以指定執(zhí)行的時機(jī)穷当,而在lifecycleScope一般執(zhí)行的都是異步的任務(wù)提茁,到異步任務(wù)執(zhí)行完成之后lifecycle.state是不確定的。如下面的例子:
lifecycleScope.launchWhenStarted {
try {
...
} finally {
...
}
}
在finally中的代碼執(zhí)行時可能lifecycle.state已經(jīng)是DESTROYED膘滨,如果在執(zhí)行一些和生命周期相關(guān)的操作就需要判斷當(dāng)前的狀態(tài)甘凭。如在DESTROYED之后再執(zhí)行UI相關(guān)的操作可能會引起錯誤,甚至閃退火邓。
如果現(xiàn)在還沒升級到Android X丹弱,又使用了MVVM相關(guān)的組件,可以自己添加擴(kuò)展的形式來實(shí)現(xiàn)铲咨,如LiveData:
inline fun <T: Any> ViewModel.liveData(
crossinline block: suspend () -> T): LiveData<State<T>>{
val liveData = MutableLiveData<RequestResult<T>>()
val job = CoroutineScope(context).launch {
liveData.postValue(State.Loading)
try {
val value = block()
liveData.postValue(State.Success(value))
}catch (e: Exception){
liveData.postValue(State.Error(e))
}
}
//需要自己處理Job的生命周期
collectJob(job)
return liveData
}
需要注意的是要自己處理協(xié)程的生命周期躲胳,避免內(nèi)存泄漏或出現(xiàn)錯誤。