一、引入
- 使用Kotlin以單例形式做了一個簡單的Retrofit封裝,因為業務需要,要將token新增到請求頭當中,所以使用了okhttp的攔截器做了簡單封裝,使其能夠滿足當前的業務需求,可以能夠動態修改攔截器中的請求頭資訊。額(⊙﹏⊙)描述實在是寫不了,還是看程式碼吧。
- 如果對於Retrofit或RxJava還不是很瞭解可以看一下我的部落格早些時候的文章瞭解一下。
二、封裝
需要的依賴
// 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"複製程式碼
程式碼
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() } }複製程式碼
簡要說明
initOkhttpClient()
方法中的日誌攔截器列印出來的header中沒有包括攔截器的header,但是從Debug結果來看,攔截器裡面的header頭確實是加上了,而且是可以修改的,Constants.TOKEN
是object
單例類Constants中的一個var變數。可以在程式碼中修改,修改之後攔截器中的header也會跟著修改。
二、使用
主要程式碼
// 順序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()) } }複製程式碼
請求介面
interface TestService { @FormUrlEncoded @POST("/api/login") fun getLoginUser(@FieldMap map: Map<String, String>): Flowable<UserBean> }複製程式碼
簡要說明
在主要程式碼中我使用了一個
LinkedHashMap
,這是因為我們的後臺要求請求的前幾個引數是有序的,所以要新增到一個順序map集合中。
UserBean
是一個物件,因為剛開始新增了字串與Gson的解析器,所以可以直接使用物件或者是類來操作。相應的在1主要程式碼中的s ->中的s也相當於是這個物件或者是字串。