0%

Kotlin中Retrofit与RxJava的简单封装

一、引入

  1. 使用Kotlin以单例形式做了一个简单的Retrofit封装,因为业务需要,要将token添加到请求头当中,所以使用了okhttp的拦截器做了简单封装,使其能够满足当前的业务需求,可以能够动态修改拦截器中的请求头信息。额(⊙﹏⊙)描述实在是写不了,还是看代码吧。
  2. 如果对于Retrofit或RxJava还不是很了解可以看一下我的博客早些时候的文章了解一下。

二、封装

  1. 需要的依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
       // 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. 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    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. 主要代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    // 顺序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. 请求接口

    1
    2
    3
    4
    5
    6
    interface TestService {

    @FormUrlEncoded
    @POST("/api/login")
    fun getLoginUser(@FieldMap map: Map<String, String>): Flowable<UserBean>
    }
  3. 简要说明

    在主要代码中我使用了一个LinkedHashMap,这是因为我们的后台要求请求的前几个参数是有序的,所以要添加到一个顺序map集合中。
    UserBean是一个对象,因为刚开始添加了字符串与Gson的解析器,所以可以直接使用对象或者是类来操作。相应的在1主要代码中的s ->中的s也相当于是这个对象或者是字符串。