I'm trying to convert my app which currently uses Retrofit, to use RX Java. In order to handle Pagination, I traditionally was grabbing the nextPage URL from the response headers.
@Override
public void success(Assignment assignment, Response response) {
response.getHeaders(); // Do stuff with header info
}
However, since switching to RX Java, i'm not sure how to get the response information from my retrofit call.
@GET("/{item_id}/users")
Observable<List<Objects>> getObjects(@Path("object_id") long object_id);
@GET("/{next}")
Observable<List<Objects>> getNextPageObjects(@Path("next") String nextURL);
Is there a way to have my retrofit calls to return my header information along with my Typed objects?
Rx gives you a very granular control over which threads will be used to perform work in various points within a stream. To point the contrast here already, basic call approach used in Retrofit is only scheduling work on its worker threads and forwarding the result back into the calling thread.
RxAndroid is a RxJava for Android extension that is only used in Android applications. RxAndroid added the Android-required Main Thread. We will need the Looper and Handler for Main Thread execution in order to work with multithreading in Android. Note: AndroidSchedulers are provided by RxAndroid.
RxJava is a Java VM implementation of ReactiveX a library for composing asynchronous and event-based programs by using observable sequences. The building blocks of RxJava are Observables and Subscribers. Observable is used for emitting items and Subscriber is used for consuming those items.
You can use
Observable<Response>
as return type to get the response details
@GET("/{item_id}/users")
Observable<Response> getObjects(@Path("object_id") long object_id);
@GET("/{next}")
Observable<Response>getNextPageObjects(@Path("next") String nextURL);
This is how the Response object would look like
You would have to then parse the headers and body from the observable
serviceClass.getNextPageObjects("next").flatMap(new Func1<Response, Observable<List<Objects>>() {
@Override
public Observable<AuthState> call(Response response) {
List<Header> headers = response.getHeaders();
GsonConverter converter = new GsonConverter(new Gson());
// you would have to change this to convert the objects to list
List<Objects> list = converter.fromBody(response.getBody(),
YourClass.class);
return Observable.from(list);
}
}
Let me spoiler this. You could intercept request and response as of OkHttp-2.2. As on OkHttp wiki says interceptors will not work in Retrofit
with OkUrlFactory
. You need to provide your Client
implementation to execute Retrofit
requests on this custom Client and directly on OkHttp
Unfortunately, it is not out yet (soon).
public class ResponseHeaderInterceptor implements Interceptor {
public interface ResponseHeaderListener{
public void onHeadersIntercepted(Headers headers);
}
private ResponseHeaderListener mListener;
public ResponseHeaderInterceptor(){};
public ResponseHeaderInterceptor(ResponseHeaderListener listener){
mListener = listener;
}
@Override public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
if(mListener != null){
mListener.onHeadersIntercepted(response.headers());
}
return response;
}
Usage:
ResponseHeaderListener headerListener = new ResponseHeaderListener(){
@Override
public void onHeadersIntercepted(Headers headers){
//do stuff with headers
}
};
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.interceptors().add(new ResponseHeaderInterceptor(headerListener));
RestAdapter.Builder restAdapterBuilder = new RestAdapter.Builder();
restAdapterBuilder.setClient(new OkHttpClient22(okHttpClient));
This is application interceptor and will be called only once.
Please note that I did all this by logic, I still don't have OkHttp-2.2. Just read about it here. I'll remove some of this text when 2.2 is latest jar.
Alternatively, you can try to create custom client and with one interface deliver the response:
public class InterceptableClient extends OkClient {
private ResponseListener mListener;
public interface ResponseListener{
public void onResponseIntercepted(Response response);
}
public InterceptableClient(){};
public InterceptableClient(ResponseListener listener){
mListener = listener;
}
@Override
public retrofit.client.Response execute(Request request) throws IOException {
Response response = super.execute(request);
if(mListener != null) //runs on the executor you have provided for http execution
mListener.onResponseIntercepted(response);
return response;
}
}
Edit: OkHttp 2.2 has been released.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With