Kotlin中Retrofit與RxJava的簡單封裝

張欽發表於2017-09-06

一、引入

  1. 使用Kotlin以單例形式做了一個簡單的Retrofit封裝,因為業務需要,要將token新增到請求頭當中,所以使用了okhttp的攔截器做了簡單封裝,使其能夠滿足當前的業務需求,可以能夠動態修改攔截器中的請求頭資訊。額(⊙﹏⊙)描述實在是寫不了,還是看程式碼吧。
  2. 如果對於Retrofit或RxJava還不是很瞭解可以看一下我的部落格早些時候的文章瞭解一下。

二、封裝

  1. 需要的依賴

     // retrofit2
     implementation "com.squareup.retrofit2:retrofit:2.3.0"
     // Gson
     implementation "com.squareup.retrofit2:converter-gson:2.3.0"
     // 字串
     implementation "com.squareup.retrofit2:converter-scalars:2.3.0"
     // RxJava
     implementation "com.squareup.retrofit2:adapter-rxjava2:2.3.0"
     // okhttp
     implementation "com.squareup.okhttp3:okhttp:3.8.0"
     implementation "com.squareup.okhttp3:logging-interceptor:3.8.0"
     // RxJava2
     implementation "io.reactivex.rxjava2:rxandroid:2.0.1"
     implementation "io.reactivex.rxjava2:rxjava:2.1.3"複製程式碼
  2. 程式碼

     object RetrofitClient {
    
         /**
          * by lazy 懶載入(延遲載入)
          */
         private val mRetrofit by lazy { createRetrofit() }
         /**
          * 預設介面實現類的例項
          */
         val gClient by lazy { createService(TestService::class.java) }
    
         /**
          * 生成介面實現類的例項
          */
         fun <T> createService(serviceClass: Class<T>): T {
             return mRetrofit.create(serviceClass)
         }
    
         private fun createRetrofit(): Retrofit {
             return Retrofit.Builder()
                     .baseUrl(Constants.BASE_URL)
                     // 設定OkHttpclient
                     .client(initOkhttpClient())
                     // RxJava2
                     .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                     // 字串
                     .addConverterFactory(ScalarsConverterFactory.create())
                     // Gson
                     .addConverterFactory(GsonConverterFactory.create())
                     .build()
         }
    
         /**
          * 每次請求都會走攔截器
          *
          * 只需要修改Constants.TOKEN就可以
          */
         private fun initOkhttpClient(): OkHttpClient {
             val builder = OkHttpClient.Builder()
             if (Constants.LOG_FLAG) {
                 // OkHttp日誌攔截器
                 builder.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
             }
    
             builder.addInterceptor { chain ->
                 val original = chain.request()
                 val request = original.newBuilder()
                         // 設定請求頭,從Debug中看到修改Constants.TOKEN請求header頭也會修改
                         .header("Authorization", Constants.TOKEN)
                         .method(original.method(), original.body())
                         .build()
                 return@addInterceptor chain.proceed(request)
             }
             return builder.build()
         }
     }複製程式碼
  3. 簡要說明

    initOkhttpClient()方法中的日誌攔截器列印出來的header中沒有包括攔截器的header,但是從Debug結果來看,攔截器裡面的header頭確實是加上了,而且是可以修改的,Constants.TOKENobject單例類Constants中的一個var變數。可以在程式碼中修改,修改之後攔截器中的header也會跟著修改。

二、使用

  1. 主要程式碼

     // 順序map
     var map = LinkedHashMap<String, String>()
     map.put("username", "sdwfqin")
     map.put("password", "123123")
    
     // 這裡呼叫的是上述封裝類中預設介面實現類的例項gClient
     RetrofitClient.gClient
             // 呼叫請求介面中的方法
             .getLoginUser(map)
             // 執行緒切換,(請求在io,操作在主)
             .compose(SdUtils.rxSchedulerHelper())
             .subscribe(
                     // 第一個相當於OnNext()
                     { s ->
                         log_e(s.toString())
                         main_tv.text = s.toString()
                         if (s.ret == 0) {
                             showToast("登入成功${s.data.user.usertoken}")
                         } else {
                             showToast("登入失敗${s.msg}")
                         }
                         hideProgress()
                     },
                     // 第二個相當於OnError()
                     { e ->
                         // e是一個異常
                         log_e(e.toString())
                         httpError()
                     }
             )
    
     ----------------------
     // 執行緒切換的程式碼
     /**
      * 統一執行緒處理
      * @param
      * @return
      */
     fun <T> rxSchedulerHelper(): FlowableTransformer<T, T> {    //compose簡化執行緒
         return FlowableTransformer { observable ->
             observable.subscribeOn(Schedulers.io())
                     .observeOn(AndroidSchedulers.mainThread())
         }
     }複製程式碼
  2. 請求介面

     interface TestService {
    
         @FormUrlEncoded
         @POST("/api/login")
         fun getLoginUser(@FieldMap map: Map<String, String>): Flowable<UserBean>
     }複製程式碼
  3. 簡要說明

    在主要程式碼中我使用了一個LinkedHashMap,這是因為我們的後臺要求請求的前幾個引數是有序的,所以要新增到一個順序map集合中。
    UserBean是一個物件,因為剛開始新增了字串與Gson的解析器,所以可以直接使用物件或者是類來操作。相應的在1主要程式碼中的s ->中的s也相當於是這個物件或者是字串。

相關文章