当前位置:   article > 正文

Android 使用retrofit+kotlin协程,搭建MVVM框架_android retrofit kotlin

android retrofit kotlin

前言

Android 上的 Kotlin 协程

协程是一种并发设计模式,您可以在 Android 平台上使用它来简化异步执行的代码。协程是在版本 1.3 中添加到 Kotlin 的,它基于来自其他语言的既定概念。

在 Android 上,协程有助于管理长时间运行的任务,如果管理不当,这些任务可能会阻塞主线程并导致应用无响应。使用协程的专业开发者中有超过 50% 的人反映使用协程提高了工作效率。本主题介绍如何使用 Kotlin 协程解决以下问题,从而让您能够编写出更清晰、更简洁的应用代码。

特点

协程是我们在 Android 上进行异步编程的推荐解决方案。值得关注的特点包括:

  • 轻量:您可以在单个线程上运行多个协程,因为协程支持挂起,不会使正在运行协程的线程阻塞。挂起比阻塞节省内存,且支持多个并行操作。
  • 内存泄漏更少:使用结构化并发机制在一个作用域内执行多项操作。
  • 内置取消支持取消操作会自动在运行中的整个协程层次结构内传播。
  • Jetpack 集成:许多 Jetpack 库都包含提供全面协程支持的扩展。某些库还提供自己的协程作用域,可供您用于结构化并发。

MVVM开发模式简述

View:Activity/Fragment

ViewModel:Jetpack ViewModel & Jetpack LiveData

Model:Repository仓库,包含本地持久性数据和服务端的数据

以下是Google Android官网对LiveData和ViewModel的定义

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。

1、项目中使用到的库

  1. // Kotlin
  2. implementation "androidx.activity:activity-ktx:1.2.0"
  3. implementation 'androidx.fragment:fragment-ktx:1.2.5'
  4. //协程
  5. implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
  6. //retrofit
  7. implementation 'com.squareup.retrofit2:retrofit:2.9.0'
  8. implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

2、创建retrofit和okhttpclient的静态类

  1. object RetrofitClient {
  2. private const val BASE_URL = "https://wanandroid.com/"
  3. private var retrofit: Retrofit? = null
  4. val service: HttpService by lazy {
  5. getRetrofit().create(HttpService::class.java)
  6. }
  7. private fun getRetrofit(): Retrofit {
  8. if (retrofit == null) {
  9. retrofit = Retrofit.Builder()
  10. .baseUrl(BASE_URL)
  11. .client(getOkHttpClent())
  12. .addConverterFactory(GsonConverterFactory.create())
  13. //.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
  14. .build()
  15. }
  16. return retrofit!!
  17. }
  18. private fun getOkHttpClent(): OkHttpClient {
  19. val builder = OkHttpClient().newBuilder()
  20. val cacheFile = File(MyApplication.instance.cacheDir, "cache")
  21. val cache = Cache(cacheFile, 1024 * 1024 * 50)// 50M 的缓存大小
  22. builder.run {
  23. cache(cache)
  24. connectTimeout(60, TimeUnit.SECONDS)
  25. readTimeout(60, TimeUnit.SECONDS)
  26. writeTimeout(60, TimeUnit.SECONDS)
  27. retryOnConnectionFailure(true)//错误重连
  28. }
  29. return builder.build()
  30. }
  31. }

3、新建接收数据的基类

  1. //接受数据的基类
  2. data class ResponseData<out T>(
  3. val errorCode: Int,
  4. val errorMsg: String,
  5. val data: T
  6. )
  7. //获取banner为例
  8. data class Banner(
  9. val desc: String,
  10. val id: Int,
  11. val imagePath: String,
  12. val isVisible: Int,
  13. val order: Int,
  14. val title: String,
  15. val type: Int,
  16. val url: String
  17. )

4、新建基类中间层BaseRepository,统一处理请求结果

  1. open class BaseRepository {
  2. suspend fun <T : Any> request(call: suspend () -> ResponseData<T>): ResponseData<T> {
  3. return withContext(Dispatchers.IO) {
  4. call.invoke()
  5. }.apply {
  6. LogUtil.e("接口返回数据---------->,${this}")
  7. when (errorCode) {
  8. 0, 200 -> this
  9. 100, 401 -> ""
  10. 403 -> ""
  11. 404 -> ""
  12. 500 -> ""
  13. else -> ""
  14. }
  15. }
  16. }
  17. }

5、新建ViewModel的基类BaseViewModel

  1. open class BaseViewModel : ViewModel(), LifecycleObserver {
  2. //运行在UI线程的协程
  3. fun launchUI(block: suspend CoroutineScope.() -> Unit) = viewModelScope.launch {
  4. try {
  5. withTimeout(15 * 1000) {
  6. block()
  7. }
  8. } catch (e: Exception) {
  9. //此处接收到BaseRepository里的request抛出的异常
  10. //根据业务逻辑自行处理代码...
  11. }
  12. }
  13. }

6、新建BaseActivity,做一些简单的封装

  1. abstract class BaseActivity<T : ViewBinding, VM : ViewModel> : AppCompatActivity() {
  2. lateinit var binding: T
  3. protected lateinit var viewModel: VM
  4. override fun onCreate(savedInstanceState: Bundle?) {
  5. super.onCreate(savedInstanceState)
  6. binding = getViewBinding()
  7. providerVMClass()?.let {
  8. viewModel = ViewModelProvider(this).get(it)
  9. }
  10. setContentView(binding.root)
  11. initView()
  12. setListener()
  13. }
  14. abstract fun providerVMClass(): Class<VM>?
  15. protected abstract fun getViewBinding(): T
  16. abstract fun initView()
  17. abstract fun setListener()
  18. }

7、以请求banner模块为例,撸一遍代码

  1. interface HttpService {
  2. @GET("banner/json")
  3. suspend fun getBanner(): ResponseData<List<Banner>>
  4. }
  5. class BannerRepository : BaseRepository() {
  6. suspend fun getBanner(): ResponseData<List<Banner>> = request {
  7. RetrofitClient.service.getBanner()
  8. }
  9. }
  10. class BannerViewModel : BaseViewModel() {
  11. private val repository by lazy {
  12. BannerRepository()
  13. }
  14. private val bannerData by lazy {
  15. MutableLiveData<List<Banner>>()
  16. }
  17. fun getBanner(): LiveData<List<Banner>> {
  18. launchUI {
  19. val result = repository.getBanner()
  20. bannerData.value = result.data
  21. }
  22. return bannerData
  23. }
  24. }
  25. class BannerActivity : BaseActivity<ActivityBannerBinding, BannerViewModel>() {
  26. override fun getViewBinding() = ActivityBannerBinding.inflate(layoutInflater)
  27. override fun initView() {
  28. viewModel.getBanner().observe(this, { it ->
  29. it.forEach {
  30. LogUtil.e(it.imagePath)
  31. }
  32. })
  33. }
  34. override fun setListener() {
  35. }
  36. override fun providerVMClass() = BannerViewModel::class.java
  37. }

8、一个retrofit配合kotlin 协程的MVVM模式的网络请求框架搭建好了

//自己总结的,可以参考一下

GitHub - withyi9223/yiwork

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/510864
推荐阅读
相关标签
  

闽ICP备14008679号