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

前言

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、项目中使用到的库

    // Kotlin
    implementation "androidx.activity:activity-ktx:1.2.0"
    implementation 'androidx.fragment:fragment-ktx:1.2.5'

    //协程
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
    
    //retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

2、创建retrofit和okhttpclient的静态类

object RetrofitClient {

    private const val BASE_URL = "https://wanandroid.com/"

    private var retrofit: Retrofit? = null

    val service: HttpService by lazy {
        getRetrofit().create(HttpService::class.java)
    }

    private fun getRetrofit(): Retrofit {
        if (retrofit == null) {
            retrofit = Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(getOkHttpClent())
                .addConverterFactory(GsonConverterFactory.create())
                //.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build()
        }
        return retrofit!!
    }


    private fun getOkHttpClent(): OkHttpClient {
        val builder = OkHttpClient().newBuilder()

        val cacheFile = File(MyApplication.instance.cacheDir, "cache")
        val cache = Cache(cacheFile, 1024 * 1024 * 50)// 50M 的缓存大小

        builder.run {
            cache(cache)
            connectTimeout(60, TimeUnit.SECONDS)
            readTimeout(60, TimeUnit.SECONDS)
            writeTimeout(60, TimeUnit.SECONDS)
            retryOnConnectionFailure(true)//错误重连
        }

        return builder.build()
    }

}

3、新建接收数据的基类

//接受数据的基类
data class ResponseData<out T>(

    val errorCode: Int,
    val errorMsg: String,
    val data: T
)

//获取banner为例
data class Banner(
    val desc: String,
    val id: Int,
    val imagePath: String,
    val isVisible: Int,
    val order: Int,
    val title: String,
    val type: Int,
    val url: String
)

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

open class BaseRepository {

    suspend fun <T : Any> request(call: suspend () -> ResponseData<T>): ResponseData<T> {
        return withContext(Dispatchers.IO) {
            call.invoke()
        }.apply {
            LogUtil.e("接口返回数据---------->,${this}")
            when (errorCode) {
                0, 200 -> this
                100, 401 -> ""
                403 -> ""
                404 -> ""
                500 -> ""
                else -> ""

            }
        }
    }

}

5、新建ViewModel的基类BaseViewModel

open class BaseViewModel : ViewModel(), LifecycleObserver {


    //运行在UI线程的协程
    fun launchUI(block: suspend CoroutineScope.() -> Unit) = viewModelScope.launch {
        try {
            withTimeout(15 * 1000) {
                block()
            }
        } catch (e: Exception) {
            //此处接收到BaseRepository里的request抛出的异常
            //根据业务逻辑自行处理代码...
          
        }
    }

    
}

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

abstract class BaseActivity<T : ViewBinding, VM : ViewModel> : AppCompatActivity() {

    lateinit var binding: T
    protected lateinit var viewModel: VM

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = getViewBinding()
        providerVMClass()?.let {
            viewModel = ViewModelProvider(this).get(it)
        }
        setContentView(binding.root)
        initView()
        setListener()

    }

    abstract fun providerVMClass(): Class<VM>?

    protected abstract fun getViewBinding(): T

    abstract fun initView()

    abstract fun setListener()
}

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

interface HttpService {


    @GET("banner/json")
    suspend fun getBanner(): ResponseData<List<Banner>>


}

class BannerRepository : BaseRepository() {

    suspend fun getBanner(): ResponseData<List<Banner>> = request {
        RetrofitClient.service.getBanner()
    }


}

class BannerViewModel : BaseViewModel() {

    private val repository by lazy {
        BannerRepository()
    }

    private val bannerData by lazy {
        MutableLiveData<List<Banner>>()
    }

    fun getBanner(): LiveData<List<Banner>> {

        launchUI {
            val result = repository.getBanner()
            bannerData.value = result.data
        }
      
        return bannerData
    }
}

class BannerActivity : BaseActivity<ActivityBannerBinding, BannerViewModel>() {


    override fun getViewBinding() = ActivityBannerBinding.inflate(layoutInflater)

    override fun initView() {
        viewModel.getBanner().observe(this, { it ->
            it.forEach {
                LogUtil.e(it.imagePath)
            }
        })
    }

    override fun setListener() {
    }


    override fun providerVMClass() = BannerViewModel::class.java
}

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

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

GitHub - withyi9223/yiwork

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
Kotlin + 协程 + Retrofit + MVVM 是一种非常优雅的方式来实现网络请求。下面是一个简单的示例: 首先,我们需要添加相关依赖库: ```gradle // Kotlin协程 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9' // Retrofit2 implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // ViewModel和LiveData implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.0' ``` 接下来,我们创建一个数据类来表示网络请求返回的数据: ```kotlin data class Response<T>( val code: Int, val msg: String, val data: T? ) ``` 然后,我们创建一个接口来描述我们的API: ```kotlin interface ApiService { @GET("api/get_data") suspend fun getData(): Response<List<String>> } ``` 注意,我们在这里使用了 `suspend` 关键字来表示这个方法是一个挂起函数。 接下来,我们创建一个 `ApiService` 的实例: ```kotlin val retrofit = Retrofit.Builder() .baseUrl("https://example.com/") .addConverterFactory(GsonConverterFactory.create()) .build() val api = retrofit.create(ApiService::class.java) ``` 现在,我们可以在我们的 ViewModel 中使用这个 `api` 对象来进行网络请求了: ```kotlin class MyViewModel : ViewModel() { private val _data = MutableLiveData<List<String>>() val data: LiveData<List<String>> = _data fun loadData() { viewModelScope.launch { val response = api.getData() if (response.code == 200) { _data.value = response.data } } } } ``` 在这里,我们使用了 `viewModelScope` 来启动一个协程来进行网络请求。如果请求成功,我们就将数据传递给 `_data` 变量,它是一个 LiveData 对象。 最后,我们可以在我们的 Activity 或 Fragment 中观察 `data` 变量来获取网络请求返回的数据: ```kotlin class MyActivity : AppCompatActivity() { private val viewModel by viewModels<MyViewModel>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_my) viewModel.data.observe(this, Observer { data -> // 在这里更新UI }) viewModel.loadData() } } ``` 这样,我们就使用 Kotlin + 协程 + Retrofit + MVVM 实现了一个优雅的网络请求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值