Kotlin协程学习3之协程与ViewModel通过viewModelScope构建网络请求基础框架(防止内存泄露)

完整完善工程代码见:

https://github.com/WeDox/AndroidXDemo3

简介:

MVVM+Kotlin Coroutines+Retrofit2+OkHttp3+Jackson构建网络请求基础工程小例子
Kotlin 协程+ViewModel的实践小例子

协程与ViewModel通过viewModelScope构建网络请求基础框架(防止内存泄露)

0、配置依赖

  //协程
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1"
    //retrofit2
    api 'com.squareup.retrofit2:retrofit:2.6.1'
    api 'com.squareup.retrofit2:converter-gson:2.6.1'
    //viewModelScope
    api 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0-beta01'

1、DemoApiService.kt

interface DemoApiService {
    @GET("poetry.php")
    suspend fun login(): BodyOut<List<RandomPoetryBean>>
}

2、DemoApi.kt

object DemoApi {
    val instance: DemoApiService by lazy {
        val retrofit = Retrofit.Builder()
                .baseUrl("http://120.78.120.117/poetry/")
                .addConverterFactory(GsonConverterFactory.create())
                .build()
        retrofit.create(DemoApiService::class.java)
    }
}

3、RandomPoetryViewModel.kt

class RandomPoetryViewModel : BaseViewModel() {

    var resultListDataLiveData = MutableLiveData<BodyOut<List<RandomPoetryBean>>>()


    fun getRandomPoetryList(onError: (String) -> Unit) {
        //viewModelScope是一个绑定到当前viewModel的作用域  当ViewModel被清除时会自动取消该作用域,所以不用担心内存泄漏为问题
        viewModelScope.launch {
            //withContext表示挂起块
            val data = withContext(Dispatchers.IO) {
                try {
                    DemoApi.instance.login()
                } catch (e: Exception) {
                    handleException(e, onError)
                }
            }
            //上面代码出现异常时,data为kotlin.Unit
            if (data is BodyOut<*>) {
                try {
                    resultListDataLiveData.value = data as BodyOut<List<RandomPoetryBean>>
                } catch (e: Exception) {
                    onError("强制转换出错${e.message}")
                }
            }
        }
    }
}

4、基础ViewModel ----》BaseViewModel.kt

public abstract class BaseViewModel : ViewModel() {
    protected fun handleException(e: Exception, onError: (String) -> Unit) {
        if (e is com.google.gson.JsonSyntaxException) {
            onError("JSON解析出错")
        } else if (e is java.net.ConnectException) {
            onError("网络链接失败")
        }/*else if(e is kotlinx.coroutines.JobCancellationException){//JobCancellationException中断异常 todo 后期过滤掉这个异常,不必处理

        }*/
        else {
            onError("未知异常${e.toString()}")
        }
    }
}

5、使用

val myViewModel = ViewModelProvider(this, RandomPoetryViewModelFactory()).get(RandomPoetryViewModel::class.java!!)
        myViewModel.resultListDataLiveData.observe(this, Observer<BodyOut<List<RandomPoetryBean>>> { dataList ->
            Log.e("ATU", "获取到数据" + dataList)
        })
        myViewModel.getRandomPoetryList {
            Log.e("ATU", "回调$it")
        }

推荐阅读更多精彩内容