I want to use AsyncTask to perform login with a server, and show a progress dialog before the connection ends.
Since there may not be response for the request, I need to set the timeout value for the AsyncTask. I found that when I simply use .execute(), the program works fine but no timeout function is implemented. When I use .get(1000, TimeUnit.MILLISECONDS), the program just halts for 1 second and no progress dialog is shown.
Any one can tell me whether the task is executed when .get(1000, TimeUnit.MILLISECONDS) is called? If yes, why there's no sign of execution; and if not, how can I implement this timeout function of the AsyncTask?
The AsyncTask.get(), if in the main thread (AKA. UI thread) will block execution.
You probably need call it in a separate thread.
Edit
Vogella made a very great article about this: AndroidPerformance: Android Threads, Handlers And AsyncTask
Take the code from here, I did and I assure you it works great without blocking the main UI thread.
I think you need to set the timeout interval on HttpUrlConnection object that would be better option to hand this situation.
If you use AndroidHttpClient it has nice preset connection timeouts.
From the documentation, the get(long timeout, TimeUnit unit) method will wait for the duration specified, then attempt to cancel the task. I think that all this will do is call cancel() on your AsyncTask, rather than performing any kind of timeout on your connection. If you are performing some kind of long download you can check isCancelled in your loop. However if you are just trying to give some kind of connection timeout then get is not the way to do it.
Please also note that get blocks the main thread until it returns. This is true of both the "timeout" version and the base version of the method. As such it is not an asynchronous operation.
To get your connection timeout, you need to perform this on the actual connection that you create, not on the task itself. There are ways of doing this for both an HttpUrlConnection and the HttpClient.
Related
Based on Android developer's document web-page AsyncTask, Thread, it is possible to send cancel() request to AsyncTask's thread. Albeit I have sent the cancellation request and it was successful, the thread stills running. Any idea to stop the execution?
button.setOnClickListener {
Log.i(TAG, asyncTaskObj.status) // RUNNING
if (asyncTaskObj.status == AsyncTask.Status.RUNNING) {
asyncTaskObj.cancel(true)
Log.i(TAG, asyncTaskObj.isCancelled) // True
}
Log.i(TAG, asyncTaskObj.status) // RUNNING
}
Plus, is there any simple alternative to AsyncTask, which let's restart execution of the thread? (Obviously restarting AsyncTask is not possible Q&A-2)
One more thing, I have read following questions Q&A-1, Q&A-2. However, the answers do not work for me. For instance, there is no isRunning variable.
P.S. My code is in Kotlin. Please share your idea in either Java or Kotlin.
It is impossible to immediately cancel a thread from the outside like that safely. You don't know what operations it might be running, what locks the thread might hold, etc. Because of that, cancel doesn't actually stop the thread immediately. It sets a flag, and it's the job of the AsyncTask to check the flag and end itself by returning from doInBackground. Do not assume any canceled thread or task will stop running instantly. If your code requires that, you need to fix your code.
As for restarting- from scratch? Create a new instance of the AsyncTask with the same parameters. From where you left off? You can do it in a couple of ways, but it takes a lot of work. And AsyncTask is not suitable for that because its thread is a shared resource among all tasks, you'll need to use an actual Thread for that.
I have really searched for this every where, I can make both synchronous and asynchronous data requests, but I can't actually understand which is asynchronous with what? and what is sync with what?
call.execute() runs the request on the current thread.
call.enqueue(callback) runs the request on a background thread, and runs the callback on the current thread.
You generally don't want to run call.execute() on the main thread because it'll crash, but you also don't want to run call.enqueue() on a background thread.
when you asynchronous, it means not in the foreground(it does not block the users interface while it accomplishes the given task), on other hand synchronous means in the foreground while your application execute things in the same thread the UI consuming.
In your case(making REST requests via retrofit or any other REST api) you must not make that in that foreground and you have to make in a background thread.
In the case of retrofit you have the following methods to make the request:
call.execute() // works in the foreground.
call.enqueue() // works in the background.
So you have a choice of two: either you make the call.enqueue directly or you can user call.execute but wrapped with a service(I mean you have to handle the background work your self).
Synchronous requests are declared by defining a return type.Synchronous methods are executed on the main thread. That means the UI blocks during request execution and no interaction is possible for this period. Using the .execute() method on a call object will perform the synchronous request. The deserialized response body is available via the .body() method on the response object.
Asynchronous requests don’t have a return type. Instead, the defined method requires a typed callback as last method parameter.Using asynchronous requests forces you to implement a Callback with its two callback methods: success and failure. When calling the asynchronous getTasks() method from a service class, you have to implement a new Callback and define what should be done once the request finishes.
Retrofit is a type-safe HTTP client for Android and Java. And I would highly recommend using this over any other library.
Do you understand what is sync and async call, or what is blocking and non-blocking call?
To answer your question, any api call you do or any heavy or time-consuming task you do on Android, it should be non-blocking (async) as it should not block the Main or UI thread in Android.
Please read this article for more understanding
https://developer.android.com/guide/components/processes-and-threads.html
As all requests in Volley are executed asynchronously on a different thread without blocking the “main thread”, is there any way to wait for the request to complete and then continue the main thread execution?
You should design your app such that it keeps the main thread live at all times. You can then have blocks of code run when the response has been received using listeners or async task. Check out my answer using listeners here. Or look at onPostExecute for AsyncTask.
is there any way to wait for the request to complete and then continue
the main thread execution?
An alternative is to show a loading dialog box while volley is working. This way you can prevent the user from interacting with your app until the request is completed (just don't forget to give him a chance to cancel).
Volley is meant to work in parallel with your main thread and tell you when the request has completed (what all apps should do) if you don't desire that, don't use Volley. But you'll get a NetworkOnMainThreadException and if you manage to bypass it, you'll end up with an ANR exception.
I am having my UI and I am starting my Socket connection to server in another thread. Problem is, I need to wait for server reply. When it arrives, I need to do specific funcions. I have found that Handler approach can be possible, but other sites are telling this is not true. What are your suggestions? Is Handler solution right and how to do it effectively? Any example?
Thanks
Have you tried using the AsyncTask?
http://developer.android.com/reference/android/os/AsyncTask.html
Perform the network operation in the doInBackground()
Once it returns the onPostExecute() will be executed by the main thread which is able to update GUI etc.
I wrote an AsyncTask and most of the time there is no delay between its constructor been called and its doInBackground been called (0 ms delay).
But whenever contacts syncing is happening at the background, I often experience 1-3 seconds delay between my AsyncTasks's constructor and doInBackground. This delay is unacceptable in my circumstances.
I understand that AsyncTask is a background thread and this problem can be solved by using Thread and setting its priority higher. But what I want to found out is, how do I know what's causing my AsyncTask's doInBackground from being called?
I used adb shell top -m 10 and the process usage seems quite normal when this issue happened.
Any help is appreciated.
thanks
I also face this issue for long period, but now it is solved. Use the code below
new AsyncTaskName().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
instead the code
new AsyncTaskName().execute();
it would solve the problem of running doInbackground late.
We generally don't bother about task scheduling by the jvm. And infact we need not to bother also.
If something needs to be done as quick as possible in your application do it in the constructor itself or use onPre of Asynctask (Remember it execute on UI thread).
But i agree there is something fishy in the doInBackgroud calling in Android AsyncTask
i itself had witnessed the doInbackground didn't get called after onPre. You can google this also. many people had faced it.
I moved to use Traditional Thread.
I wrote my own Asynctask using Traditional thread at core and to mimic onPre and onPost i used Handler. You can go for that option also.
It's important to distinguish between creating and executing the task. (An ASyncTask has a separate execute() method, as well as a constructor, as you have noticed.)
Creating a thread is potentially quite expensive, so you might find that creating the task in advance, and then only executing it at the correct time, gives better results.
If the background operation is likely to be repeated often, you may also find that an IntentService, which handles requests one-at-a-time in a background thread, is more suitable.