一、框架搭建介绍协程+Retrofit+ViewModel+LiveData+DataBinding的框架搭建,实现从网络请求api接口功能,相关demo
1.1、环境、依赖库配置整体项目结构如下
新建项目,在app的build.gradle中添加依赖
//retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
//coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0-RC-native-mt'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0-RC-native-mt'
//viewModels
implementation "androidx.activity:activity-ktx:1.1.0"
因为涉及到http网络请求,配置manifest权限
application节点下的http权限
android:networkSecurityConfig="@xml/network_security_config"
xml -> network_security_config.xml
app的build.gradle中配置databinding
android {
...
dataBinding {
enabled = true
}
}
gradle.properties中配置debug包运行
android.injected.testOnly=false1.2、创建api网络请求
新建UserApi.kt,这里简单实现数据解析的User实体类,服务器返回json
{
"name": "jason",
"address": "California"
}
// 定义User数据实体类
data class User(val name: String, val address: String)
// retrofit网络请求
val userServiceApi: UserServiceApi by lazy {
val retrofit = retrofit2.Retrofit.Builder()
.client(OkHttpClient.Builder().addInterceptor {
it.proceed(it.request()).apply {
Log.d("jason", "request:${code()}")
//Log.d("jason", "boy:${body()?.string()}")
}
}.build())
.baseUrl("http://81.68.175.49:8080/kotlinstudyserver/")
.addConverterFactory(MoshiConverterFactory.create())
.build()
retrofit.create(UserServiceApi::class.java)
}
// 请求接口
interface UserServiceApi {
@GET("user")
fun loadUser(@Query("name") name: String) : Call
@GET("user")
suspend fun getUser(@Query("name") name: String) : User
}
1.3、创建viewmodel
创建MainViewModel继承自ViewModel()
class MainViewModel: ViewModel() {
}
根据google官方指南,我们是在ViewModel中通过repository去请求网络、数据库的数据
因此这里还需要新建UserRepository
class UserRepository {
suspend fun getUser(name: String): User {
return userServiceApi.getUser(name)
}
}
因为这里继承自ViewModel,所以这里带了viewModelScope
MainViewModel部分代码:
class MainViewModel: ViewModel() {
//liveData
val userLiveData = MutableLiveData()
private val userRepository = UserRepository()
fun getUser(name: String) {
viewModelScope.launch {
userLiveData.value = userRepository.getUser(name)
}
}
}
1.4、加载数据
activity_main.xml中绘制mvvm绑定视图
activity中加载数据set到布局上
class MainActivity : AppCompatActivity() {
private val mainViewModel: MainViewModel by viewModels()
@SuppressLint("StaticFieldLeak")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 设置布局
val binding =
DataBindingUtil.setContentView(this, R.layout.activity_main)
// 指定viewModel
binding.viewModel = mainViewModel
// 在 xml 中使用 LiveData
binding.lifecycleOwner = this
binding.submitButton.setOnClickListener {
mainViewModel.getUser("xxx")
}
}
}
二、设计好在哪里
2.1、viewModel解决Activity很可能会被销毁重建,页面的状态将会丢失
2.2、协程解决了回调地狱的问题如下图所示页面旋转时,CoroutineDemo数据销毁了,而使用了ViewModel的数据仍然存在
在网络请求中,协程将异步任务同步化,优化了代码可读性



