一、引入
- 使用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也相当于是这个对象或者是字符串。