Kotlin中Retrofit网络请求简单封装

2,194 阅读3分钟

使用Kotlin简单的对Retrofit+RxJava大多数普通请求进行封装

提示:如果对Kotlin,RxLifecycle,Retrofit,RxJava等不太了解的小伙伴可以参考网上的基础资料

1.惯例先添加依赖

    //Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
    //RxJava
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
    implementation 'io.reactivex.rxjava2:rxjava:2.0.1'
    //rxlifecycle
    implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.1.0'
    //解析相关
    implementation 'com.alibaba:fastjson:1.2.34'
    //kotlin
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
    //Kotlin反射库 Kotlin使用反射则添加
    implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"

2.封装请求Retrofit接口

通常来说我们一个应用可能只有一个BaseUrl,此处只对Retrofit接口进行了单例封装

public class RetrofitUtils {

    private RetrofitUtils() {
    }

    private static class Tool {

        static IApiServer defaultServer = initRetrofitServer(NetConfig.BASE_URL);

        static IApiServer initRetrofitServer(String baseUrl) {
            int DEFAULT_TIME = 15;    //默认超时时间

            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.readTimeout(DEFAULT_TIME, TimeUnit.SECONDS);
            builder.connectTimeout(DEFAULT_TIME, TimeUnit.SECONDS);
            //        builder.addInterceptor(new LoggingInterceptor());//使用自定义的Log拦截器
            OkHttpClient client = builder.build();
            return new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(FastJsonConverterFactory.create())
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(client)
                    .build()
                    .create(IApiServer.class);
        }
    }

    public static IApiServer getDefaultServer() {
        return Tool.defaultServer;
    }

}

3.请求响应的封装

对于有格式规律的返回结果进行封装,比如以下格式

{
    "code": "200",
    "data": {}
    "msg": "成功"
}

每次请求都会固定的返回code和msg,而data才是真正的数据。定义一个实体类,格式如下:

public class BaseResponse<T> {
    @JSONField(name = "status")
    public int status;
    @JSONField(name = "data")
    public T data;
    @JSONField(name = "msg")
    public String msg;
}

4.请求函数的封装

ApiCodeType中封装了部分状态和错误的tips 大家可以根据自己的情况进行编写

对于状态拦截如果业务很复杂大家也可以抽取成拦截器等方式

object RetrofitUtilsKt {

    /**
     *   Activity 中绑定声明周期 处理数据请求统一函数
     *   @param observable 请求接口Observable实例
     *   @param lifecycleProvider 可谓空 如果为空不绑定声明周期
     *   @param showDialog 是否显示LoadView 默认显示
     *   @param onNext 成功回调
     *   @param onError 失败回调
     *   @param showDialog 是否显示loadView
     */
    fun <T> runRxA(observable: Observable<T>,
                   lifecycleProvider: LifecycleProvider<ActivityEvent>?,
                   onNext: (data: T) -> Unit,
                   onError: (codeType: ApiCodeType) -> Unit,
                   showDialog: Boolean = true): Disposable {
        var dialog: AlertDialog? = null
        //绑定lifecycle
        val realObservable = if (lifecycleProvider != null)
            observable.compose(lifecycleProvider.bindUntilEvent(ActivityEvent.DESTROY))
        else
            observable

        return realObservable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe {
                    //请求之前 显示loadView等操作
                    if (lifecycleProvider is Activity && showDialog) {
                        dialog = DefaultUtils.showProgressDialog(lifecycleProvider)
                    }
                }
                .subscribe(Consumer<T> {
                    dialog?.apply { dismiss() }
                    //数据错误
                    if (it == null || (it is BaseResponse<*> && it.data == null)) {
                        onError(ApiCodeType.DATA_ERROR)
                        return@Consumer
                    }
                    //根据业务需求拦截部分状态
                    if (it is BaseResponse<*>) {
                        when (it.status) {
                            ApiCodeType.LOGON_EXPIRED.code ->{ //拦截代码 }
                            else -> onNext(it)
                        }
                    } else {
                        onNext(it)
                    }
                }, Consumer<Throwable> {
                    dialog?.apply { dismiss() }
                    onError(ApiCodeType.OTHER_ERROR)
                })
    }
}

此处只展示了绑定Activity生命周期的函数,如果大家需要绑定Fragment生命周期更换LifecycleProvider的泛型为FragmentEvent即可。

5.扩展函数的封装

对于普通简单请求通常我们只关心三要素,请求接口(包括参数)、关联生命周期(Activity等)、结果回调。

在Kotlin中可对任意类型添加扩展函数,根据此特性我们对必要类型之一(请求接口)编写以下函数便于使用:

fun <T> Observable<T>.runRxA(lifecycleProvider: LifecycleProvider<ActivityEvent>?,
                             onNext: (data: T) -> Unit,
                             onError: (codeType: ApiCodeType) -> Unit,
                             showDialog: Boolean = true) =
        RetrofitUtilsKt.runRxA(this, lifecycleProvider, onNext, onError, showDialog)

6.使用

Kotlin中单参数lamdba无需显示声明,可用it表示,代码中注释为当前it类型。

        RetrofitUtils
                .getDefaultServer()
                .getContractInformationEdit(bean)
                .runRxA(this, { 
                //成功
                //it:BaseResponse<ContractInformationBean>
                }, {
                //失败
                //it:ApiCodeType
                    toast(it.msg)
                })

结尾

希望本文对各为小伙伴有所帮助,如果错误或者疑问欢迎留言指出。:)