How to get intermediate response from Retrofit API call? - android

I using Retrofit to making API call. All API call is working fine except one where its returning huge response around 15k records.
Issue is when made call progress bar is being shown infinitely until I get response. And as response too huge getting OOM exception.
As an solution I found that need to use #Streaming annotation. I used that but didn't get intermediate callback. I want API should return chunk of response one by one.
Please help me.
public static ServiceInterface getServiceAPIClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
Gson gson = new GsonBuilder()
.setLenient()
.create();
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(
new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder();
builder = request.newBuilder();
if (!TextUtils.isEmpty(PrefsHelper.getAccessTokenEdrm())) {
builder.addHeader(AUTHORIZATION, PrefsHelper.getAccessTokenEdrm());
}
builder.addHeader(API_VERSION, "1.0")
.addHeader("Accept", "application/json");
request = builder.build();
return chain.proceed(request);
}
}).connectTimeout(5, TimeUnit.MINUTES) .readTimeout(5, TimeUnit.MINUTES).addInterceptor(interceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
return retrofit.create(ServiceInterface.class);
}
API Method
#POST(EdrmConstants.SEARCH_DOCUMENTS)
#Streaming
Observable<ResponseBody> searchDocuments(#Body DocumentRequest documentRequest);

15k records is too match.
Retrofit needs time to make http request and makes serialization to your ResponseBody.class
I sure serialization takes main time.
I guess most right solution is to edit request on server side to split data on pages with 200-500 records.

Related

Headers in Retrofit with Android

I've been reading about Retrofit and I got to the point of Headers and I don't know if I understood them too well. In the course I'm doing it uses them to establish an authentication with a user created in the backend and a database and it does it in two different ways:
private WebServiceBA() {
loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.level(HttpLoggingInterceptor.Level.BODY);
httpClientBuilder = new OkHttpClient.Builder().addInterceptor(loggingInterceptor);
httpClientBuilder.addInterceptor(chain -> {
Request original = chain.request();
Request.Builder requestBuild = original
.newBuilder()
.addHeader("Authorization", AUTH_USER)
.method(original.method(), original.body());
Request request = requestBuild.build();
return chain.proceed(request);
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL_BA)
.client(httpClientBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
In this first form I understand that the Header is passing through code but I don't understand the .method(original.method(), original.body());. And in this one it's passing it through the Retrofit call itself:
#GET("/todos_profesores_admin")
Call<List<ProfesorBA>> listAllProfesorAdmin(#Header("Authorization") String authHeader);
I don't understand if "Authorization" is something that should be like that since it's in the backend or it's a way to call it in the code.
I suppose that by doing it in the call, in this case we have more freedom since we pass him the users that we want, but what other things can we send through the Header of a Retrofit call or how far does its usefulness extend? Thank you very much.

Android Retrofit Interceptor add body param for all calls

Is there any way to edit the body of a network call for adding a default attribute used in the 95% of the calls?
I've seen that a query parameter is pretty easy to add (link)
But, I have not seen it for a Body.
My problem is that I'm working with an old API that asks me to send in each request the token. So I need to add this line in most of the classes.
#SerializedName("token") val token: String
Any ideas?
You should use httpInterceptor to solve this problem if you send in header
final OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
// add token key on request header
// key will be using access token
.addHeader("token", yourToken)
.build();
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
Edit : Im sorry, I've realized now you ask about sending in body.
I think it can be possible with old way(without Gson, Moshi etc). It is really more annoying than adding to every request.

Web-service call from android app takes 10 mins to reflect the latest results

Am Struggling with one of the issues of being service taking almost 10 mins to reflect the updated results. Actually, am using an API of type Get, the structure of the service is like this:
www.abc.net/wp-json/wp/v2/posts?categories=192&page=1&per_page=2
When I try to call the service from the browser it's showing the updated information, but when I try to call the same service from my android app using retrofit it's delaying the updated response by almost 10 mins.
Here is the code mentioned in my last question about the same :
public class ApiClient {
private static Retrofit retrofit = null;
public static Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.cacheControl(CacheControl.FORCE_NETWORK)
.addHeader("Cache-Control", "no-cache")
.addHeader("Cache-Control", "no-store");
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.SERVICE_ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}
}
My API Interface
public interface ApiInterface {
String SERVICE_ENDPOINT = "https://example.com/wp-json/wp/v2/";
#GET("posts")
Call<ArrayList<CategoryResponse>> fetchlatestposts(#Query("bloglist")
int bloglist);
}
What can be the issue for not getting the updates response in real time, while as after 10-15 mins of pause it will give the updated results.
The issue was from the server side, WordPress has cache enabled which was causing the issue.

Retrofit convert multipart body back to file

I am using multipart for uploading data to server. The problem is that the backend developer told me that the file I was uploading became corrupted during upload.
So is there any way to test those file locally? Like can I convert a file to multipart and then reconvert it to file to test it?
I am using Retrofit 2
Thanks
ask your backend developer whether he want file as binary or as base64 if it is image and then send file accordingly
you can also log what data is being sent in body of your post
here is code to log data you are sending through retrofit
public class RetrofitClient {
private RetrofitClient() {
}
public static Retrofit getApiClient(String baseHost) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
// set your desired log level
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging);
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header(Util.HEADER_KEY, ""+Util.HEADER_VALUE); // <-- this is the important line
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseHost)
.addConverterFactory(new NullOnEmptyConverterFactory())
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
return retrofit;
}
}

Add Response call back when using retrofit with rxjava

I am using retrofit with Rxjava to get response from API as you can see the method i am using i can't see what's coming in the response and offcourse i don't need to becuase i am providing GsonConverter to retrofit but for some debugging reason i need to see the response that coming from API. How can i do this, what code i need to add.
public interface ProductApiService
{
String END_POINT = "http://beta.site.com/index.php/restmob/";
#GET(Url.URL_PRODUCT_API)
Observable<Product> getProducts(#Query("some_id") String cid);
class Creator
{
public static ProductApiService getProductAPIService() {
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ProductApiService.END_POINT)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
return retrofit.create(ProductApiService.class);
}
}
}
You can only do this as of Retrofit 2: Change the return type to include Response:
#GET(Url.URL_PRODUCT_API)
Observable<Response<Product>> getProducts(/* ...etc... */);
You can also use Observable<Result<Product>> if you want to see all possible errors in onNext (including IOException, which normally uses onError).
Daniel Lew's approach is quick and contains the least amount of boiler plate code. However, this may force you to refactor your networking logic. Since you mention needing this for debugging purposes, perhaps using a configured OkHttpClient with Interceptors is a less intrusive strategy.
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request req = chain.request();
Response resp = chain.proceed(req);
// ... do something with response
return resp;
}
})
.build();
Retrofit retrofit = new Retrofit.Builder()
.client(httpClient)
.baseUrl(ProductApiService.END_POINT)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();

Categories

Resources