-
-
Notifications
You must be signed in to change notification settings - Fork 460
FAQ
集成了RxHttp,却找不到toObservableResponse(Class)方法?
生成了RxHttp类,却没有toObservableXxx方法?
@DefaultDomain、@Doman、@Param、@Parser、@OkClient、@Converter
如果你使用kapt/annotationProcessor
依赖rxhttp-compiler
,则会在编译期间检索以上6个注解,如果一个注解都未检索到,就不会工作(ksp检索不到注解,照样工作),也就不会生成RxHttp类;
所以,如果你使用kapt
依赖了rxhttp-compiler
,则需要手动使用以上任一注解
注意:rxhttp-compiler只会在本Module检索注解,故请不要在A Module依赖rxhttp-compiler,却在B Module使用以上任一注解,即使A依赖B或者B依赖A
ksp、kapt、annotationProcessor 用法及区别
检查步骤如下:
- 检查是否有依赖
rxhttp-compiler
如:
//x.x.x为具体版本号
ksp/kapt/annotationProcessor 'com.github.liujingxing.rxhttp:rxhttp-compiler:x.x.x'
-
检查依赖
rxhttp-compiler
的Module有没有使用以上任一注解,如果没有,请手动使用其中一个 -
如果项目集成了kotlin,请使用
ksp/kapt
关键字依赖注解处理器,并且要导入kotlin-kapt/ksp
插件,如下:
plugins {
// ksp/kapt choose one
// id 'kotlin-kapt'
id 'com.google.devtools.ksp' version 'x.x.x-x.x.x' //x.x.x-x.x.x 为ksp版本号
}
dependencies {
ksp/kapt 'com.github.liujingxing.rxhttp:rxhttp-compiler:x.x.x’ (x.x.x为具体版本号)
}
- 最后rebuild一下项目,这是必须的
经过以上步骤,就会在build
文件夹下生成RxHttp类,然而,少部分人的项目会将build
文件夹设置为忽略,如下:
此时项目中build
文件夹下的类是无法被引用到的,需要你在上面配置中将build
文件夹移除,此时项目中就可以引用到RxHttp
类。
经过以上步骤后还未生成RxHttp类,请联系我。
首先,明确一点,该问题并不是RxHttp的问题,而是项目中其它代码存在问题,导致编译不通过,从而无法生成RxHttp类,只需要在Android studio中的错误列表中,找出罪魁祸首,把它解决即可,如下图所示:
rxhttp-compiler只会在本Module检索注解,检索不到,就不会生成相关方法,故请不要在A Module依赖rxhttp-compiler,却在B Module使用注解
-
1、该方法是通过RxJava实现的,需要你依赖RxJava
-
2、该方法是通过自定义解析器+注解在编译期间通过
rxhttp-compiler
自动生成的,详情查看自定义Parser
toObservableXxx方法内部是通过RxJava实现的,所以需要你单独依赖RxJava,并告知RxHttp你依赖的RxJava版本,如下:
dependencies {
//rxjava2 (RxJava2/Rxjava3二选一,使用toObservable系列方法时必须)
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.github.liujingxing.rxlife2:rxlife-rxjava2:2.2.2' //管理RxJava2生命周期,页面销毁,关闭请求
//rxjava3
implementation 'io.reactivex.rxjava3:rxjava:3.1.6'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'
implementation 'com.github.liujingxing.rxlife:rxlife-rxjava3:2.2.2' //管理RxJava3生命周期,页面销毁,关闭请求
}
通过ksp告知RxHttp你依赖的RxJava版本
ksp {
//依赖了RxJava时,rxhttp_rxjava参数为必须,传入RxJava版本号
arg("rxhttp_rxjava", "3.1.6")
}
通过kapt告知RxHttp你依赖的RxJava版本
kapt {
arguments {
//依赖了RxJava时,rxhttp_rxjava参数为必须,传入RxJava版本号
arg("rxhttp_rxjava", "3.1.6")
}
}
通过javaCompileOptions告知RxHttp你依赖的RxJava版本
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [
//使用toObservableXxx方法时必须,传入你依赖的RxJava版本
rxhttp_rxjava: '3.1.6',
]
}
}
}
}
注:ksp/kapt/javaCompileOptions选其一
配置好后,rebuild即可
token过期涉及到具体的业务逻辑,RxHttp不可能做出深度封装。但在Demo中,已经有相关案例,详细请查看TokenInterceptor类。
RxHttp默认在IO线程发请求,也默认在IO线程回调,可以通过以下两种方式将回调切换到主线程
//方式1 通过RxAndroid
RxHttp.get("/service/...")
.toObservableString()
.observeOn(AndroidSchedulers.mainThread()) //通过RxAndroid切换主线程
.subscribe(s -> {
}, throwable -> {
});
//方式2,通过RxLife
RxHttp.get("/service/...")
.toObservableString()
.as(RxLife.asOnMain(this)) //kotlin 使用lifeOnMain(this)替代
.subscribe(s -> {
}, throwable -> {
});
第一种方式不依赖于任何环境,任何地方都可直接调用;
第二种方式依赖于FragmentActivity/Fragment/ViewMode/View等环境,既切换主线程,又可绑定当前环境生命周期,做到页面销毁,自动关闭请求
有两种方式,如下:
//方式1 监听各个回调
RxHttp.get("/service/...")
.toObservableString()
.observeOn(AndroidSchedulers.mainThread()) //控制下游在主线程执行
.doOnSubscribe(disposable -> {
//请求开始
})
.doFinally(() -> {
//请求结束,不管成功/失败都会回调
})
.subscribe(s -> {
//请求成功
}, throwable -> {
//请求失败
});
//方式2 自定义Observer对象,订阅时传入
public class LoadingObserver<T> implements Observer<T>() {
@Override
public void onSubscribe(Disposable d) {
//请求开始,显示弹窗
}
@Override
public void onNext(T t) {
//请求成功
}
@Override
public void onError(Throwable e) {
//请求失败,销毁弹窗
}
@Override
public void onComplete() {
//请求完成,仅在成功时才会回调 ,销毁弹窗
}
}
RxHttp.get("/service/...")
.toObservableString()
.observeOn(AndroidSchedulers.mainThread()) //控制下游在主线程执行
.subscribe(new LoadingObserver<String>());
注: 第二种方式,onComplete回调,仅在请求成功时才会回调
服务器正常情况下返回如下格式
{"code":200,"msg":"success","data":{}}
然而在异常情况下,返回的data
字段却是五花八门,如:
//data是空字符串
{"code":100,"msg":"fail","data":""}
//或者 data是详细的错误描述
{"code":100,"msg":"fail","data":"请求失败"}
//甚至 data是一个数组对象
{"code":100,"msg":"fail","data":[]}
此时,如果我们传入对象去解析data
字段,必将解析失败,从而拿不到code
、msg
字段。
对于以上情况,我们分两种场景:
1、客户端不需要data
字段
现实开发中,客户端常会遇到不需要data
字段的接口,例如关注接口,不管成功/失败,我们只需要拿到code
字段,给出对应的提示即可,所以此时,我们不用管服务端返回的data
字段是什么样的,因为我们用不上,故我们只需要传入String
类型去解析data
字段即可,如下:
RxHttp.get("/service/...")
.toObservableResponse(String.class) //传入String类型,不管服务端返回的data字段是什么类型,都不会解析失败
.subscribe(s -> {
}, throwable -> {
});
然而,还有一种情况,服务端可能不返回data
字段,此时我们传入的String类型的data
字段就会为null
,而自定义解析器不允许返回null
(RxJava不允许传递null值),故我们需要在解析器里做下额外的判断,如下:
@Override
public T onParse(okhttp3.Response response) throws IOException {
Response<String> data = Converter.convertTo(response, Response.class, types)
T t = data.getData();
if (t == null && types[0] == String.class) {
//判断我们传入的泛型是String对象,就给t赋值""字符串,确保t不为null
t = (T) "";
}
if (data.getCode() != 200 || t == null) {
throw new ParseException(String.valueOf(data.getCode()), data.getMsg(), response);
}
return t;
}
以上代码,会在data
字段为null
时,判断我们传入的泛型是不是String类型,是的话,赋值空字符串,确保data不为空,这样就能确保数据正常解析。
2、客户端需要data
字段
正常情况,data是一个对象,而异常情况下,服务端返回data为""
或者[]
,这样如果我们直接用Gson一次性解析,肯定会报JsonSyntaxException
异常,此时,我们只能分两步解析,如下:
@Override
public T onParse(okhttp3.Response response) throws IOException {
//第一步,解析code、msg字段,把data当成String对象
Response<String> data = Converter.convertTo(response, Response.class, String.class)
T t = null;
if (data.getCode() == 200) { //假设200代表正常情况
//第二步,取出data字段,转换成我们想要的对象
t = GsonUtil.getObject(data.getData(), types[0]);
}
if (t == null && types[0] == String.class) {
//判断我们传入的泛型是String对象,就给t赋值""字符串,确保t不为null
t = (T) "";
}
if (data.getCode() != 200 || t == null) {
throw new ParseException(String.valueOf(data.getCode()), data.getMsg(), response);
}
return t;
}
以上代码,结合了第一种客户端不需要data字段
的情况,第一步就是先解析code、msg字段,如果code正确,再去解析data字段,这样就确保解析不会抛出异常。
该方法RxJava2才有,RxJava3请使用to
操作符替代,如:to(RxLife.to(this))
或to(RxLife.toMain(this))
RxHttp内部并不会直接抛出超时异常,超时异常是由OkHttp
抛出,RxHttp
负责原样传递而已,所以,遇到超时问题,请不要怀疑是RxHttp的问题,你可根据以下规则去排查超时原因:
- 先检查网络问题,
流量、wifi
都试试,还是超时,换个手机再试试 - 使用postman等工具试试正常响应时间需要多久,如果正常响应时间都比较慢,在代码中可以适当加大超时时间,RxHttp内部默认的读、写、连接超时均为10s,如何配置超时时间,点击这样
- 如果是下载遇到偶现超时问题,请不要在下载链接后带时间戳等动态参数(即每次发请求,key对应的参数值都不一样),因为大多数服务器都有自带缓存,如果你每次传递的参数都不一样,服务器就不会走缓存,下载可能就会很慢,从而导致超时