I use Rxjava and Retrofit to handle the response from an HTTP server.
Most of the time, data response is in this format:
{
code: 'OK',
data: {.....}
}
And sometimes, the data
property doesn't exist:
{
code: 'OK'
}
I make a BaseResponse
class.
public class BaseResponse<T> implements Serializable {
private String code;
private String msg;
private T data;
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
public T getData() {
return data;
}
}
And make a Map
function to parse it:
public static <T> Function<BaseResponse<T>, T> applyUnwrapResponse () {
return new Function<BaseResponse<T>, T>() {
@Override
public T apply(@NonNull BaseResponse<T> baseResponse) throws Exception {
if (baseResponse.getCode().equals(Constants.SUCCESS_CODE)) {
// http returned from server
T data = baseResponse.getData();
if (data == null) {
return null; // throw exception: The mapper function returned a null value
return return new T(); // syntax error
// how ?
}
return data;
} else if (baseResponse.getCode().equals(Constants.USER_NOT_LOGGED_IN)) {
// auth token error
throw new UserNotLoginException(baseResponse.getMsg());
}
// unknown error
throw new UnknownServerException(baseResponse.getMsg());
}
};
}
When data
property doesn't exist, I try to return null
, but this is not allowed in Rxjava2.
In the customize Observer, I handle all success
scenarios in onNext(), so I need to emit an error when data == null
.
but I can not return null, and also cannot return a T
by return new T()
, so how should I do? Anyone can help me out?
Several suggested options:
BaseResponse
object and check the nullity of data property object at the Subscriber/Observer.You can simply wrap your T value with some Optional
alike interface, which can have a value, or can have nothing (Java8 Optional
probably not available with android, but you can come up with simple structure like Optional
yourself), then on your onNext()
you can check whether you have a value or not.
RxJava2 has new Observable
type called Maybe, which either emit a single item - onSuccess
notification, or nothing - onComplete()
notification, (and also errors):
onSubscribe (onSuccess | onCompleted | onError)?
You can use flatMapMaybe
with both Observable
or Single
(from the Retrofit service interface), to map some response value to a Maybe
, in the flatMapMaybe
you can use Maybe.fromCallable
to return null like you did here, Maybe.fromCallable
will treat returned null as no items emitted, and you'll get onComplete()
, so you can distinguish between result case (onNext
) to the no items case (onComplete
).