I'm using OkHttp at the first time. I see the tutorial said that If wanna use Response Caching, I must call new OkHttpClient() exactly once (a singleton instance). OkhttpClient is thread-safe by synchronized methods. But in my application, there are many threads connects to the network to get remote data simultaneously, some threads must wait for a thread have done getting data to execute its operation.
So Is it's performance not better than normal?
If yes, If I don't enable Reponse Caching, should I call new OkHttpClient() many times for better performance?
Thanks
For the best performance, share a single OkHttpClient instance. This allows your cache to be shared, and in the future when we implement fancy joining & cancelling it’ll allow outgoing requests to be merged.
Related
I have a case where some users end up in a loop of requesting #GET API call too often.
Too often = 10-20x every second.
Currently, I've not located the problem and it seems that it's not going to be an easy fix, but I was wondering, is there a possibility to set some kind of limitations on Retrofit2, where if the app goes into some kind of loop where single API request is called so many times, it actually ignores these requests, for instance, do 1-5x same requests in a second max. or something similar?
How could this be done (from a networking library settings perspective)? (Till I find the root cause, I'd like to protect backend)
According the this answer you can use dispatcher as below:
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(1);
OkHttpClient client = new OkHttpClient.Builder()
.dispatcher(dispatcher)
.build()
After then you will be able to send one request on a time.
Apologies if this is too simple of a question, I am new to using remote data sources.
I assume Enqueue is running on background threads instead of main thread, but which is faster and better for optimization? As I understand using Runnables will take up more code, but I have seen multiple apps built with such a method, is it better than the simpler Enqueue method?
Retrofit will use underlying OkHttp to make calls to the server. Enqueue is tested and it is always better to use the globally recognized by developers with performance testing and lots of other aspects around it. It also covers your ExecutorService without you having to write the implementation for it. I'll add few points for readers new to OkHttp.
new Request.Builder().url(endpoint).build() creates the request but
doesn't send anything.
client.newCall(request).execute() sends the request and waits for
the response, but doesn't download the response, only its headers so
you can check things like response.isSuccessful() immediately.
response.body().string() downloads the body of the response and
returns a string.
You can push your own implementation of ExecutorService like this
OkHttpClient.Builder().dispatcher(Dispatcher(executorService)).build()
I've noticed from profiling that when my OkHttpClient is being created by the builder, TrustManagerFactory.getTrustManagers seems to be taking a long time and is blocking my UI thread on startup. It takes about 111 millis to complete.
Not being extremely familiar with TrustManagers, I was wondering if there might be a faster method that's still secure to provide these to the OkHttpClient, and remove this as a concern.
In the mean time, I'll see if I can't defer the creation of my OkHttpClient to a background thread.
You should be able to call
OkHttpClient client = new OkHttpClient.Builder().sslSocketFactory(sslSocketFactory, trustManager).build();
https://github.com/square/okhttp/blob/4568075b1a163bec48a8598917e6d6bcc9b2d96b/okhttp/src/main/java/okhttp3/OkHttpClient.java#L655
But ultimately this is doing what you will need to do, triggering the JVM to load loading SSL related classes, load CA certificates from the system etc. So it seems unlikely this is a performance win.
Creating the OkHttpClient on a background thread sounds like the best option.
I have to send four different request in an api at the same time. Do i need to make AsyncTask background thread for each request or all request could be done through a single AsyncTask. Can somebody please help.
This is a concurrency issue. There is literally dozens of ways to do this in Android. I've written almost every single one for courses that cover this material... and even then it isn't 'simple'.
I'd personally make use of HaMeR (Handler, Messages, Runnable) framework of Android. Create 4 runnables and have them post their results to a Handler.
However... That isn't the easiest to implement. and would require you to understand how to safely create your own custom handler (making use of WeakReference properly, etc.)
Therefore, I'd recommend running the asyncTask(s) on the executorService
myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); The default thread pool executor should start with 4 threads (I believe off-hand without looking it up).
I am assuming you are using HttpURLConnections. Unfortunately each of those connections, as specified in the documentation, is capable of handling only a single request.
However, you can (and possibly should) still perform all your requests in a single AsyncTask. Each AsyncTask will require the creation of a new thread which takes lots of time and resources. So don't listen to anyone who tells you to create a new task for each request.
You also have the option of exploiting HTTP persistence. If you add the header Connection: Keep-Alive to your request via connection.setRequestProperty("Connection", "Keep-Alive");, you will be able to send multiple requests over the same connection and save a lot of time and resources.
It's a little complicated in Java, because of the one-request-per-httpurlconnection rule, but it can be done. First, when you are done with your first request's HttpURLConnection do not close that connection. Then, to create the next connection, call url.openConnection() on the same URL object that you used to create your first HttpURLConnection. The JVM will know to reuse that connection if possible to save bandwidth.
You also have the option of using HTTP/2.0 multiplexing, which allows you to send multiple requests literally at the same time. Unfortunately I am not yet well versed enough in HTTP/2.0 to tell you exactly how to make use of this, but the multiplexing feature was included to solve exactly this problem.
In an Android app, I have to make multiple GET requests to a URL in order to transmit data to an external server (that's how the third party API works).
Data comes in sporadically. I store this data in a queue and want to send it to the server in a background asynchronously without slowing down the main UI thread. Each unit of data in the queue requires a GET request. The queue has to be emptied even if the app closes.
What's the best practice to do this? Please post/direct me to code/tutorials.
What's the best practice to do this?
That would depend on what "this" is and where this work is being done.
If "this" is "asynchronous work", you will use threads in one form or fashion:
If your HTTP operations are driving a UI, you might use AsyncTask, so you can update the UI safely from onPostExecute()
If your HTTP operations are purely in the background, and you want to do one at a time, use an IntentService, which has its own background thread and work queue
If your HTTP operations are purely in the background, and you want to do one at at time, and you are concerned about ensuring that the device should stay awake while all this is going on, consider my WakefulIntentService
If your HTTP operations are purely in the background, but you feel that you want to do several at a time, roll your own Service that uses an Executor with your own thread pool, making sure that you shut down that service when the work is done (as IntentService does), and making sure that the device stays awake with a WakeLock (and perhaps a WifiLock)
Etc.
If "this" is "HTTP GET" requests, use:
HttpUrlConnection, or
HttpClient, or
OkHttp (wrapper around those with added benefits), or
Retrofit (if your GET requests are really Web service calls), or
Volley (if you like your HTTP wrapper code to be undocumented, unsupported, but Googly)
Any number of other third-party wrapper libraries
If "this" is "queue", use the Queue class, or LinkedBlockingQueue if you plan on having multiple threads work with it at once.
If "this" is something else, I can't help you, as I'm tired of guessing.
You could do your own async HTTP GET calls using AsyncTask but I would recommend against it unless you're doing it from a learning point of view. If you want a nice, clean and stable solution I'd suggest that you use the well known Android Asynchronous Http Client 3rd party library. From the site:
"An asynchronous callback-based Http client for Android built on top of Apache’s HttpClient libraries. All requests are made outside of your app’s main UI thread, but any callback logic will be executed on the same thread as the callback was created using Android’s Handler message passing."
Making a GET is as easy as:
AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
System.out.println(response);
}
});