Android Kotlin + 协程 + Retrofit + MVVM优雅的实现网络请求(简洁!!!)

9,975 阅读1分钟

最近学习了Kotlin,感受就是好处太多了 欲罢不能,这其中协程这个特点处理异步非常不错,于是花了很长时间结合Retrofit封装了网络请求,感觉非常简洁好用。

准备工作:Retrofit的初始化 常规写法

引入第三方

implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.okhttp3:logging-interceptor:4.2.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"

BaseResponse

class BaseResponse<T> {
    val data: T? = null;
    val errorCode: Int? = null;
    val errorMsg: String? = null;
    var exception: Exception? = null;
}

Api接口

interface ApiInterface {
    @GET("/article/listproject/0/json")
    suspend fun getListProject(): BaseResponse<ListProjectBean?>
}

初始化

使用顶层函数和懒加载初始化ApiInterface 

val Api: ApiInterface by lazy {
    Retrofit.Builder()
        .baseUrl("https://www.wanandroid.com")
        .addConverterFactory(GsonConverterFactory.create())
        .client(getOkHttpClient())
        .build().create(ApiInterface::class.java)
}

private fun getOkHttpClient(): OkHttpClient {
    val builder: OkHttpClient.Builder = OkHttpClient.Builder()
        .readTimeout(30, TimeUnit.SECONDS) //设置读取超时时间
        .writeTimeout(30, TimeUnit.SECONDS) //设置写的超时时间
        .connectTimeout(30, TimeUnit.SECONDS)
    if (BuildConfig.DEBUG) {
        val httpLoggingInterceptor = HttpLoggingInterceptor()
        builder.addInterceptor(httpLoggingInterceptor.apply {
            httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
        })
    }
    return builder.build()
}

开始调用

一:最简单的调用

class MainVm : BaseViewModel() {
    val responseText=ObservableField<String>("11111");

    /**
     * 请求网络
     */
    fun requestData(){
        viewModelScope.launch {
            request {
                getListProject();
            }.next {
                Log.e("data===>","data=====>${this.data}")
                responseText.set(this.data.toString())
            }
        }
    }
}

所有请求都是再ViewModel中进行的,因为我使用了viewModelScope可以防止内存泄漏。调用起来是不是特别简洁

这里说明一下 viewModelScope.launch就是开启一个协程,不用多说,然后里面调用了request方法请求网络,这个方法我封装再BaseViewModel中。getListProject方法就是定义再ApiInterface 的网络接口,后面next方法就是请求成功的处理(next方法仿照kotlin的apply方法实现的),   之所以用next名称是因为之前一直再用Rxjava。然后调用的时候默认开启请求的对话框的。

二:关闭对话框的请求

class MainVm : BaseViewModel() {
    val responseText=ObservableField<String>("11111");

    /**
     * 请求网络
     */
    fun requestData(){
        viewModelScope.launch {
            request(false) {
                getListProject();
            }.next {
                Log.e("data===>","data=====>${this.data}")
                responseText.set(this.data.toString())
            }
        }
    }
}

request传入false即可,最后是不是还得加个获取异常,其实也很简单。

三:异常获取

class MainVm : BaseViewModel() {
    val responseText=ObservableField<String>("11111");

    /**
     * 请求网络
     */
    fun requestData(){
        viewModelScope.launch {
            request(false) {
                getListProject();
            }.next {
                Log.e("data===>","data=====>${this.data}")
                responseText.set(this.data.toString())
            }.catchException { 
                when(this){
                    is ApiException->{
                        
                    }
                    is IOException->{
                        
                    }
                    else->{
                        
                    }
                }
            }
        }
    }
}

是不是超级简单,后面加上catchException 方法就获取到了所有的异常,当然request方法里面已经对异常统一处理了,不过demo里面统一处理为简单的土司

感觉这样封装调用起来真方便,这还得益于kotlin的lambda表达式 和带有接收者的函数的方便

详细的就不多说了 看demo吧,github地址:

github.com/wangxiongta…

欢迎提供意见建议

使用kotlin的flow封装见这篇文章

juejin.cn/post/696355…