I'm very new to programming and I have some doubts.
I have a AsyncTask which is I call as RunInBackGround.
and I start this process like:
new RunInBackGround().execute();
But I wish to wait until this call is finish its executing, before proceeding to the other statements of code.
How can I do that?
Are there any way for it?
wait until this call is finish its executing
You will need to call AsyncTask.get() method for getting result back and make wait until doInBackground execution is not complete. but this will freeze Main UI thread if you not call get method inside a Thread.
To get result back in UI Thread start AsyncTask as :
String str_result= new RunInBackGround().execute().get();
Although optimally it would be nice if your code can run parallel, it can be the case you're simply using a thread so you do not block the UI thread, even if your app's usage flow will have to wait for it.
You've got pretty much 2 options here;
You can execute the code you want waiting, in the AsyncTask itself. If it has to do with updating the UI(thread), you can use the onPostExecute method. This gets called automatically when your background work is done.
If you for some reason are forced to do it in the Activity/Fragment/Whatever, you can also just make yourself a custom listener, which you broadcast from your AsyncTask. By using this, you can have a callback method in your Activity/Fragment/Whatever which only gets called when you want it: aka when your AsyncTask is done with whatever you had to wait for.
In your AsyncTask add one ProgressDialog like:
private final ProgressDialog dialog = new ProgressDialog(YourActivity.this);
you can setMessage in onPreExecute() method like:
this.dialog.setMessage("Processing...");
this.dialog.show();
and in your onPostExecute(Void result) method dismiss your ProgressDialog.
AsyncTask have four methods..
onPreExecute -- for doing something before calling background task in Async
doInBackground -- operation/Task to do in Background
onProgressUpdate -- it is for progress Update
onPostExecute -- this method calls after asyncTask return from doInBackground.
you can call your work on onPostExecute() it calls after returning from doInBackground()
onPostExecute is what you need to Implement.
I think the easiest way is to create an interface to get the data from onpostexecute and run the Ui from interface :
Create an Interface :
public interface AsyncResponse {
void processFinish(String output);
}
Then in asynctask
#Override
protected void onPostExecute(String data) {
delegate.processFinish(data);
}
Then in yout main activity
#Override
public void processFinish(String data) {
// do things
}
Related
why should we use onProgressUpdate() method in Asynctask class,
i am using onPreExecute() and onPostExecute() along with doInBackground() but never used onProgressUpdate,In which cases we will use this method.
Thanks in Advance for your response.
onProgressUpdate(Progress...), invoked on the UI thread after a call
to publishProgress(Progress...). The timing of the execution is
undefined. This method is used to display any form of progress in the
user interface while the background computation is still executing.
For instance, it can be used to animate a progress bar or show logs in
a text field.
As you read, you can publish your async task progress by using this.
protected void onProgressUpdate(Integer... progress) {
showProgressPercent(progress[0]);//write your own codes
}
Source
onProgressUpdate() is used to better the user experience by updating the user about the background process initiated at some time. For more information, refer to the docs.
AsyncTask lifecycle : onPreExecute -> doInBackground -> onPostExecute
onPreExecute is calling on MainThread. which means you can touch views.
doInBackground is calling on BackgroundThread. which means you can't touch views.
onPostExecute is calling on MainThread.
so while your job is going on inside doInBackground, you may want to notify user about job's progress but you can't notify user because it's calling on BackgroundThread. you need to jump to MainThread and AsyncTask provides you onProgressUpdate function to make it.
you can call publishProgress inside doInBackground.
I am trying to dismiss dialog on onCancelled(Boolean aBoolean) of AsyncTask :
1. It will get called if I call 'myAsyncTask.cancel(true)' if AsyncTask is running.
2. It won't get called if AsyncTask already called onPostExecute().
Do anyone has idea?
Actually, AsyncTask.cancel() doesn’t kill the Thread with no regard for the consequences. All it does is set the AsyncTask to a “cancelled” state. It’s up to the developer of AsyncTask to adhere cancel state.
One of the strategies is to check isCancelled() from time to time and act appropriately. onPostExecute you can also read “cancelled” state and call onCancelled() (or any other function with common logic) manually.
In short, You can't not.
When you called .cancel(true) methods, AsyncTask execute onCancelled instead of onPostExecute.
onPostExecute means Background Tasks is over, back to UI Thread.
I think there is new way.
In onPostExecute, just adding boolean isProcessing = true;
when you don't process onPostExecute, just switch isProcessing's value to false. (I'm not sure about that way)
#Override
protected void onPostExecute(Long result) {
if (isProcessing) {
Log.d(TAG, "onPostExecute - " + result);
}
}
I am doing a geocoding get request using AsyncTask which needs to finish executing, before proceeding to call another AsyncTask which will use the results from the geocoding request to make another call to another endpoint from the MainActivity.
I thought about forcing it to loop in a while using a "done" flag, set by the first AsyncTask, that may not even work however and it seems very hacky. Does anybody have an idea how to handle this?
AsyncTasks have the hook method onPostExecute(), where you can process its results.
From there, you can simply trigger any methods you want to be executed after the AsyncTask is finished.
For example:
protected void onPostExecute(Long yourResult) {
processYourResult(yourResult);
// Method startMoreLogic() will be executed after the AsyncTask is finished.
startMoreLogic();
}
make your asynctask as a private class and put everything that wait for result at onPoseExecute().
Or add .get() to the method where you call your asynctask.
Due to android doc , The task can be executed only once.
I'm trying to run HttpClient in UI-Thread. But it allows for the only once. If I want to get another data from another link which is not yet run at the first start, how can I do it? Until I get all data when the app starts for the first time, it takes long time. Is there anyone who knows how to solve this problem ?
You're running a network operation on main thread. Use async task to run network operations in background thread (do your http requests in a background thread).
Do your networking in an async task like this:
class WebRequestTask extends AsyncTask{
protected void onPreExecute() {
//show a progress dialog to the user or something
}
protected void doInBackground() {
//Do your networking here
}
protected void onPostExecute() {
//do something with your
// response and dismiss the progress dialog
}
}
new WebRequestTask().execute();
Here are some tutorials for you if you don't know how to use async tasks:
http://mobileorchard.com/android-app-developmentthreading-part-2-async-tasks/
http://www.vogella.com/articles/AndroidPerformance/article.html
Here are the official docs from Google:
https://developer.android.com/reference/android/os/AsyncTask.html
You can call the async task multiple times whenever needed to perform the download tasks. You can pass parameters to the async task so that you can specify what data it should download (for example by passing a different url each time as a parameter to the async task). In this way, using a modular approach, you can call the same aync task multiple times with different parameters to download the data. The UI thread wont be blocked so the user experience will not be hindered and your code will be thread safe too.
You can do multiple operations in an AsyncTask
protected Void doInBackground(Void param...){
downloadURL(myFirstUrl);
downloadURL(mySecondUrl);
}
An AsyncTask can only be executed once. This means, if you create an instance of AsyncTask, you can only call execute() once. If you want to execute the AsyncTask again, create a new AsyncTask:
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute(); //Will work
myAsyncTask.execute(); //Will not work, this is the second time
myAsyncTask = new MyAsyncTask();
myAsyncTask.execute(); //Will work, this is the first execution of a new AsyncTask.
I seem to have consistent problems with timing threads and dialog windows. I've tried using a thread, or onCreate/onPrepare, or an AsyncTask to do some downloading/processing in the background. More often than not, when the background processing completes and dismisses the dialog window, control seems to return to the root thread (Activity/UI thread?) before the dialog is gone or the onPostExecute-like process is done. This makes me think I'm doing it incorrectly. Here is a typical structure (pseudo-code):
public class X {
protected String result = null;
protected ProgressDialog progressDialog;
public void onCreate() {
...
new XTask().execute();
progressDialog.show();
// result is null here, should be "hi"?
// do things with result, like barf on a NPE...sigh
}
private class XTask extends AsyncTask {
protected doInBackground() {
// Get URL.
// Look at contents, takes a few seconds.
// Return the result (should get sent to onPostExecute).
}
protected onPostExecute(r) {
result = r;
progressDialog.dismiss();
}
}
}
I would think that, after doPostExecute sets result and dismisses the dialog, processing then continues in the onCreate method. However, result is often (not always) null at this point in onCreate. Is there a better way to do this? Is this just due to the general crappiness of the emulator?
Thanks.
Edit: To be more concrete, my task (in doInBackground) fetches a URL and does a little processing on the response. This process takes 1-3 seconds. Then, theoretically, onPostExecute sets X.result to what was fetched. I know the URL content is valid and the response is good (not null). The problem is that during those 1-3 seconds, control returns to onCreate, as if the progressDialog never lived at all (it doesn't get displayed in the emulator at all, but that's normal I guess).
I had thought that calling dialog.show() was a blocking method, i.e., the dialog appeared and that method wouldn't continue until it disappeared, but that doesn't seem to be the case. Either my progressDialog.dismiss() is getting called before it should, before setting X.result, or not getting called at all, or dismiss() is happening faster/before the assignment, or something else entirely is going wrong...
Changing the order of the execute and progressDialog doesn't help, nor does moving it into onPreExecute(). Strangely, onPostExecute doesn't get called until I return in onCreate. If I have a Thread.sleep loop after execute (I thought giving it time would help), it never finishes the task until that loop finishes and I return. e.g.:
new XTask().execute();
int z=0;
while (response == null && z < 50) {
Thread.sleep(500);
z++;
}
if (response == null) return;
The task's onPostExecute method doesn't get called until "return". Hmmm...maybe being in onCreate is affecting it.
A ProgressDialog is usually used to block user interaction during loading or heavy processing but the main UI thread will continue to execute.
If you wish to perform some operation on the result you must do it in either onPostExecute of XTask or after you have gotten the result in doInBackground.
private class XTask extends AsyncTask {
#Override
protected void onProgressUpdate(/*params*/){
//modify UI
}
protected doInBackground() {
// Get URL.
// Look at contents, takes a few seconds.
//Option A: Now have the result, do some other processing here
//Cant modify UI components from here, If you need to modify a UI component from
//here call publishProgress() and modify the component in onProgressUpdate()
// Return the result (should get sent to onPostExecute).
}
protected onPostExecute(r) {
result = r;
//Option B do some processing on the result
//You can modify UI components from here
progressDialog.dismiss();
}
}
I would show the progress dialog before triggering the AsyncTask. Normally, when an AsyncTask gets executed, it takes a while to finish itself and in that time, the rest of the task calling method has already run. But in your case the task returns instantly which is probably why the dialog shows up AFTER the postexecute gets called under the AsyncTask.
I would think that, after doPostExecute sets result and dismisses the dialog, processing then continues in the onCreate method.
This is not true, when you call new XTask().execute() in UI thread, application create a worker thread and start running whatever you defied in AsyncTask.doInBackground() on this work thread, at this point (after calling new XTask().execute()), UI thread continue execute code after new XTask().execute().
The point you are talking about where your work thread finish and return to UI thread is AysncTask.onPostExecute(), this method is guaranteed to be called on UI thread after AsyncTask finish. this is the reason why it is called AsyncTask. Both of UI thread and work thread are running asynchronously.
If you want to make your UI thread blocked and wait for AsyncTask finish after XTask().execute(), you can to this:
XTask xTask = new XTask();
xTask.execute();
progressDialog.show();
xTask.get() // <-- this will make your UI thread blocked and wait for AsycnTask at this point
// result is null here, should be "hi"?
This is possible but not a good practice, as AsyncTask.get() will block execution on calling thread so probably get ANR exception.
To sum up
1. AysncTask.onPostExecute() is where process return from worker thread to UI thread, we don't care where and when it will be called on UI thread, we just need ensure it will be called on UI thread properly at some point in the future.
2. AsyncTask.get() by calling this method actually make you AsyncTask running synchronously with the calling thread.
Putting code into the task's onPostExecute should work, a simple test suggests it will (for me). However, I ended up writing a different solution which also works. I put most of the code into a Handler on the activity, which separates it from the UI thread entirely. My onCreate simply shows the loading ProgressDialog window and that's it--it just sits there, "loading". The background task does its thing and when finished, sends a message to the handler. This message tells the handler to dismiss the loading dialog and populate the list. If there are errors, different messages are sent and the handler shows an error dialog.