概述
前言
使用kotlin协程也有一段时间了,给我最大的感受就是完全可以替代Rxjava了,并且写起来更加的简洁。
6月份Retrofit发布的2.6.0版本内部支持了kotlin协程中的挂起(suspend)修饰符,这就意味着我们可以更加方便的用Retrofit结合kotlin协程来实现网络请求了。
之前我都是使用Rxjava2+Retrofit实现网络请求的功能,然后加入了AutoDispose来实现自动解绑以免发生内存泄漏的问题,感兴趣的可以看看AutoDispose代替RxLifecycle优雅的解决RxJava内存泄漏问题
那协程有没有自动解绑的东西呢。当然有了
目前google官方也给我们提供了androidx.lifecycle:lifecycle-viewmodel-ktx
的依赖包,给ViewModel中扩展了一个作用域叫viewModelScope
viewModelScope是一个绑定到当前viewModel的作用域 当ViewModel被清除时会自动取消该作用域,所以不用担心内存泄漏为问题
那这样一来,我们完全可以使用Retrofit+Coroutines这个方案来代替之前用Retrofit+Rxjava+AutoDispose的方案了。
话不多说,直接上代码
我在网上找了个公开的API接口 https://www.apiopen.top/novelApi
我们就请求这个接口了
添加依赖
首先是添加需要的依赖包,如下
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.1.0'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.1"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.1"
implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0"
implementation "com.squareup.okhttp3:okhttp:4.2.0"
implementation "com.squareup.retrofit2:retrofit:2.6.1"
implementation "com.squareup.okhttp3:logging-interceptor:4.2.0"
implementation "com.squareup.retrofit2:converter-gson:2.6.1"
代码
在看下面的代码之前,你可能需要先看一下下面几篇文章,如果你都知道的话 直接跳过即可
对ViewModel和LiveData 还不是很了解的话先看一下这篇文章
mvp过渡到mvvm(Android 架构组件)
关于一些好用的扩展方法,看一下这个
Kotlin基于RxJava的扩展方法(超级好用)
这里我们主要是看对数据类的扩展,节省一些无用代码
关于Retrofit的工厂类这里我就不放出来了,估计大家的代码都差不多,需要的可以看demo,这里我就不再浪费篇幅,直接用了。
实体类
响应基类
data class BaseResp<T>(
var code: Int = 0,
var msg: String = "",
var `data`: T
)
小说数据实体类
package com.yzq.coroutineretofitmvvm.bean
import com.google.gson.annotations.SerializedName
data class Fiction(
var bid: String = "",
var bookname: String = "",
var introduction: String = "",
@SerializedName("book_info")
var bookInfo: String = "",
var chapterid: String = "",
var topic: String = "",
@SerializedName("topic_first")
var topicFirst: String = "",
@SerializedName("date_updated")
var dateUpdated: Int = 0,
var author: String = "",
@SerializedName("author_name")
var authorName: String = "",
@SerializedName("top_class")
var topClass: String = "",
var state: String = "",
var readCount: String = "",
var praiseCount: String = "",
@SerializedName("stat_name")
var statName: String = "",
@SerializedName("class_name")
var className: String = "",
var size: String = "",
@SerializedName("book_cover")
var bookCover: String = "",
@SerializedName("chapterid_first")
var chapteridFirst: String = "",
var chargeMode: String = "",
var digest: String = "",
var price: String = "",
var tag: List<String> = listOf(),
@SerializedName("is_new")
var isNew: Int = 0,
var discountNum: Int = 0,
@SerializedName("quick_price")
var quickPrice: Int = 0,
var formats: String = "",
@SerializedName("audiobook_playCount")
var audiobookPlayCount: String = "",
var chapterNum: String = "",
var isShortStory: Boolean = false,
var userid: String = "",
@SerializedName("search_heat")
var searchHeat: String = "",
@SerializedName("num_click")
var numClick: String = "",
@SerializedName("recommend_num")
var recommendNum: String = "",
@SerializedName("first_cate_id")
var firstCateId: String = "",
@SerializedName("first_cate_name")
var firstCateName: String = "",
var reason: String = ""
)
定义请求接口
这个没什么好说的,需要注意的就是我们的方法前面用 suspend 修饰
interface ApiService {
@GET("https://www.apiopen.top/novelApi")
suspend fun getFictions(): BaseResp<List<Fiction>>
}
用于解析响应数据的扩展方法
/*数据解析扩展函数*/
fun <T> BaseResp<T>.dataConvert(): T {
if (code == 200) {
return data
} else {
throw Exception(msg)
}
}
ViewModel
注释也很详细了,这里就不多说了
class NetViewModel : ViewModel() {
var fictions = MutableLiveData<List<Fiction>>()
fun getFictions() {
/*viewModelScope是一个绑定到当前viewModel的作用域 当ViewModel被清除时会自动取消该作用域,所以不用担心内存泄漏为问题*/
viewModelScope.launch {
try {
/*dataConvert扩展函数可以很方便的解析出我们想要的数据 接口很多的情况下下可以节省不少无用代码*/
val data =RetrofitFactory.instance.getService(ApiService::class.java)
.getFictions().dataConvert()
/*给LiveData赋值 ui会自动更新*/
fictions.value = data
} catch (e: Exception) {
/*请求异常的话在这里处理*/
e.printStackTrace()
Log.i("请求失败", "${e.message}")
}
}
}
}
Activity
Activity中代码就很简单了,主要就是创建ViewModel示例,更新ui
class MainActivity : AppCompatActivity() {
private lateinit var netViewModel: NetViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
/*创建viewmodel*/
netViewModel = ViewModelProviders.of(this).get(NetViewModel::class.java)
btn.setOnClickListener {
/*请求数据*/
netViewModel.getFictions()
}
/*数据发生变化时更新ui*/
netViewModel.fictions.observe(this, Observer {
tv.text = Gson().toJson(it)
})
}
}
下面我们来看看运行结果:
可以看到,网络请求的功能已经实现了。
那对比RxJava的实现方式,你觉得哪种方式更好呢?
好了,本篇文章到此结束。
demo
如果你觉得本文对你有帮助,麻烦动动手指顶一下,算是对本文的一个认可,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!
最后
以上就是鲤鱼八宝粥为你收集整理的Retrofit+kotlin Coroutines(协程)+mvvm(Jetpack架构组件)实现更简洁的网络请求的全部内容,希望文章能够帮你解决Retrofit+kotlin Coroutines(协程)+mvvm(Jetpack架构组件)实现更简洁的网络请求所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复