I want to implement multiple parallel request in Retrofit 2.
I have the following structure to make 3 request :
HistoricalRApi.IStockChart service=HistoricalRApi.getMyApiService();
//^BVSP,^DJI,^IXIC
Call<HistoricalDataResponseTimestamp> call1= service.get1DHistoricalDataByStock("^IXIC");
Call<HistoricalDataResponseTimestamp> call2= service.get1DHistoricalDataByStock("^DJI");
Call<HistoricalDataResponseTimestamp> call3= service.get1DHistoricalDataByStock("^GSPC");
call1.enqueue(retrofitCallbackAmerica());
call2.enqueue(retrofitCallbackAmerica());
call3.enqueue(retrofitCallbackAmerica());
}
I have read that in Retrofit1, when defining the rest adapter one can define parallel request with .setExecutor like here:
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(END_POINT)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setExecutors(Executors.newFixedThreadPool(3), null)
.build();
My question is how can i achieve the same in Retrofit 2? Thanks in advance
Thanks to Colin Gillespie link i have implemented what Jake Wharton says and this is the result:
public static IStockChart getMyApiService() {
OkHttpClient client=new OkHttpClient();
Dispatcher dispatcher=new Dispatcher();
dispatcher.setMaxRequests(3);
client.setDispatcher(dispatcher);
// OkHttpClient client = new OkHttpClient();
// HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
// interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
// client.interceptors().add(interceptor);
if(myService ==null){
Retrofit retrofit=new Retrofit.Builder()
.baseUrl("http://chartapi.finance.yahoo.com/")
.addConverterFactory(JsonpGsonConverterFactory.create())
.client(client)
.build();
myService=retrofit.create(IStockChart.class);
return myService;
} else {
return myService;
}
}
Related
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.
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.
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();
I have set a global timeout in my Retrofit adapter by doing
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setReadTimeout(20, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(20, TimeUnit.SECONDS);
retrofit = new Retrofit.Builder()
.client(okHttpClient)
.build();
Great! But I would like to set an specific timeout for certain requests
E.g.
public interface MyAPI {
#GET()
Call<Void> notImportant (#Url String url);
#GET
Call<Void> veryImportant(#Url String url);
So veryImportant calls I would like a timeout of 35 seconds but notImportant the default
Is this possible?
My research has fallen flat.
I came across this however but not sure if it will work in Retrofit
https://github.com/square/okhttp/wiki/Recipes#per-call-configuration
Thank you for reading. Please help.
You can do that by creating overloaded method of your retrofit object factory method. It's maybe look like this.
public class RestClient {
public static final int DEFAULT_TIMEOUT = 20;
public static <S> S createService(Class<S> serviceClass) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
OkHttpClient client = httpClient.build();
okHttpClient.setReadTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.client(client)
.build();
return retrofit.create(serviceClass);
}
public static <S> S createService(Class<S> serviceClass, int timeout) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
OkHttpClient client = httpClient.build();
okHttpClient.setReadTimeout(timeout, TimeUnit.SECONDS);
okHttpClient.setConnectTimeout(timeout, TimeUnit.SECONDS);
Retrofit retrofit = new Retrofit.Builder().baseUrl(APIConfig.BASE_URL)
.client(client)
.build();
return retrofit.create(serviceClass);
}
}
if you want to call api with default timout, you can call it look like this.
MyAPI api = RestClient.createService(MyAPI.class);
api.notImportant();
And use the second one if you want to call api with authentication:
int timeout = 35;
MyAPI api2 = RestClient.createService(MYAPI.class, timeout);
api2.veryImportant();
Another solution is by creating different method with different OkHttpClient configuration instead of creating overloaded method. Hope this solution fix your problem.
The question is how to combine all these 3 libraries in one project?
Make one OkHttpClient to be a background layer for both Picasso and Retrofit.
How to make Priority changes like in Volley lib. (for pagination)?
In a nutshell:
OkHttpClient okHttpClient = new OkHttpClient();
RestAdapter restAdapter = new RestAdapter.Builder().setClient(new OkClient(okHttpClient)).build();
OkHttpDownloader downloader = new OkHttpDownloader(okHttpClient);
Picasso picasso = new Picasso.Builder(this).downloader(downloader).build();
I do not think it's possible to have priorities with the current version of Retrofit.
For OkHttpClient 3.0 and Retrofit 2.0 it is:
OkHttpClient client = new OkHttpClient.Builder()
.cache(cache) // optional for adding cache
.networkInterceptors().add(loggingInterceptor) // optional for adding an interceptor
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://api.yourdomain.com/v1/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
Picasso picasso = Picasso.Builder(context)
.downloader(new OkHttp3Downloader(client))
.build();
Prioritization has been moved down the stack model to the http client, and there is an issue being studied: https://github.com/square/okhttp/issues/1361