一、引入
- 使用Kotlin以单例形式做了一个简单的Retrofit封装,因为业务需要,要将token添加到请求头当中,所以使用了okhttp的拦截器做了简单封装,使其能够满足当前的业务需求,可以能够动态修改拦截器中的请求头信息。额(⊙﹏⊙)描述实在是写不了,还是看代码吧。
- 如果对于Retrofit或RxJava还不是很了解可以看一下我的博客早些时候的文章了解一下。
二、封装
需要的依赖
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"代码
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
56object 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也会跟着修改。
二、使用
主要代码
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())
}
}请求接口
1
2
3
4
5
6interface TestService {
fun getLoginUser(Map<String, String>) map: : Flowable<UserBean>
}简要说明
在主要代码中我使用了一个
LinkedHashMap
,这是因为我们的后台要求请求的前几个参数是有序的,所以要添加到一个顺序map集合中。
UserBean
是一个对象,因为刚开始添加了字符串与Gson的解析器,所以可以直接使用对象或者是类来操作。相应的在1主要代码中的s ->中的s也相当于是这个对象或者是字符串。