前言
优雅的写法请直接看最后
更新RxJava2之后,就不能在onNext里面发送null值了。但是项目中有些接口,例如更新用户密码的接口(我就遇到了),后台没有返回数据(也就是null),于是修改密码成功,但是活动crash(没有走onNext方法,而是走onError方法,但是异常对象也是null,提示Null is not a valid element),在网上找到了一片文章当Retrofit2+RxJava2遇到为null的返回结果,但是原谅我没看懂,哭(┬_┬),返回结果还是会走到onError里,我们最终的目的是要返回到onNext里
正题
下面说一下我的解决方法
利用map操作符,把被观察者(null)转换成不为null的任意对象再传递给观察者
问题没有解决之前是这样写的
public static void updateUserPassword(String oldPwd,String newPwd,Observer<Object> observer){
ApiSubscribe(RetrofitCreateHelper.getDocServiceApi().updateUserPassword(oldPwd,newPwd),observer);
利用map操作符后是这样写的
/**
* 修改密码,由于请求返回null,而RxJava2的onNext()方法不允许传入null,所以这里利用map操作符转换被观察者(事件)类型
* @param oldPwd
* @param newPwd
* @param observer
*/
public static void updateUserPassword(String oldPwd,String newPwd,Observer<String> observer){
ApiSubscribe(RetrofitCreateHelper.getDocServiceApi().updateUserPassword(oldPwd,newPwd).map(new Function<Object, String>() {
@Override
public String apply(Object optional) throws Exception {
return optional == null? "1":"2";
}
}),observer);
}
下面是更新优雅的写法:
第一步,自定义ConvertFactory
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;
public class NullOrEmptyConvertFactory extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
final Converter<ResponseBody,?> delegate = retrofit.nextResponseBodyConverter(this,type,annotations);
return new Converter<ResponseBody, Object>() {
@Override
public Object convert(ResponseBody value) throws IOException {
if (value.contentLength() == 0) return null;
return delegate.convert(value);
}
};
}
}
第二步:修改接口返回类型
import retrofit2.Response;
@GET("device/code")
Observable<Response<Device>> getDeviceByCode(@Query("code") String code);
//由原来的Observable<Device> 改成 Observable<Response<Device>>
第三步:
在现有的ConvertFactory之前添加自己定义的ConvertFactory
return new Retrofit.Builder()
.baseUrl(Constant.apiUrl)
.addConverterFactory(new NullOrEmptyConvertFactory())
.addConverterFactory(GsonConverterFactory.create(new GsonBuilder().serializeNulls().create()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(getHttpClient())
.build();
第四步:对返回结果判断
subscribe(new BaseObserver<Response<Device>>(mContext) {
@Override
public void onNext(Response<Device> device) {
TLog.e("device success");
if (null == device.body()){
//如果接口返回成功,但是返回值为null,就会走到这里
}
}
第五步完成:提示,如果不修改返回值的话,仍然会走到onError,而不会走到onNext()