21

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?

user3169791
  • 351
  • 2
  • 3
  • 9

2 Answers2

16

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

enter image description here

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);
    }

}
rahul.ramanujam
  • 5,608
  • 7
  • 34
  • 56
  • Using this type of observable makes it difficult two zip calls together, at least from what I can tell. Is there any other way? – Brandon Aug 30 '16 at 16:55
  • how about checking if response isSuccessful() ?? – orium Oct 16 '17 at 16:59
  • 2
    `Observable>` this can give you both the response body and the header information. Therefore, if you're looking for a full response with the header and body use it. – Kidus Tekeste Mar 20 '20 at 15:35
3

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.

Nikola Despotoski
  • 49,966
  • 15
  • 119
  • 148