Kotlin中Retrofit網路請求簡單封裝

L_T發表於2018-05-15

使用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)
                })
複製程式碼

結尾

希望本文對各為小夥伴有所幫助,如果錯誤或者疑問歡迎留言指出。:)

相關文章