I have an activity that displays a number. The number is obtained from SharedPreferences e.g
int num=pref.getInt(myAsyncTask.MYNUMBER,0);
The SharedPreference is loaded inside an AsyncTask where calculations take place (that involve retrieving data from db and so on). So, OnCreate() of the activity I run the Asynctask to calculate the value. However, the value is not always updated to the latest one when I launch the activity. This might be because Asynctask takes more time to calculate the new value than the the action of displaying the value inside the activity. How can I delay the execution of the method displaying the value until the Asynctask finishes with the process of the new one?
[[EDIT]]
I removed sharedpreferences. I use the onPostExecute() method to get the result. However, the behaviour is similar. The result is returned after the value is displayed so i couldn't see anything at all.
If the calculation doesn't take more than few second, the simplest solution is to use AsyncTask.get(), this method will block UI thread execution and make UI thread waiting for AsyncTask to finish:
public void onCreate(Bundle savedInstanceState) {
... ...
MyAsyncTask myAsyncTask = nee MyAsyncTask();
myAsyncTask.execute();
myAsyncTask.get(); // alternatively you can use AsyncTask.(long timeout, TimeUnit unit)
... ...
}
Bear in mind that it blocks UI thrread execution, if your calculation is longer than 5 seconds, you will probably get ANR exception.
Since you already use AsyncTask, a more reasonable solution is moving execution of the method displaying the value into AsyncTask.onPostExecute(), this is the exactly reason why AsyncTask exist in API to solve this kind if scenario.
Just use listener concept, or just 'pass' your Activity to your asynctask so It can call the main thread.
If the value is not showing as correct at the time you launch the activity you should set the visibility of the View to View.GONE so it doesn't appear, then change the visibility back to visible when you have the result. To update the value you could implement a listener on your activity that gets called by the AsyncTask.
If its going to take a significant time (more than a few seconds) you might want to also use a progress dialog so the user understands that they need to wait.
Related
My situation is this:
first I call first AsyncTask which fetched required Items from database. After that, I call another AsyncTask, which fetches these Item images.
I am getting data from AsynTasks by using callback.
Here is the issue - since I am using callback, in my class I have method processFinish which returns AsyncTask data when it finishes its computation. The problem is with two Async tasks which depend on each other. What should I do now?
You can use the get() method of asyncTask that will wait for the output and wont proceed further
also you can use it with a timeout.
ex new BackgroundTask().execute.get();
or
new BackgroundTask.execute.get(long timeout);
You could execute one AsyncTask inside another, but you should do it inside onPostExecute() because this method runs on the UI thread.
#Override
protected void onPostExecute(Void args) {
new AsyncTask2.execute(..); // Start second task once you've got first results
}
And you call your method processFinish(..) only once, after the second AsyncTask is completed.
Anyway, is there a reason why you use two AsyncTasks ? With your explanations we could believe that you might be able to use only one task.
I am working on app that updates data for every 8 secs and the update was done using Async task. I am using loops to achieve this condition
while(const_val > update_val) {
new Asynctask().execute();
Thread.sleep(8000);
}
const_val will be constant and will be not be changed by any other methods.lets say this value will be 5.update_val will be updated and decremented when Asynctask is called and let's the value will be 10. So , the while loop executes until the condition is true and asynctask ,sleep are called .
When I use above while loop in a general method then UI gets locked and if I use the same loop in another asynctask there was an error saying "Only original thread that created a view hierarchy can touch its view "
You need to change your code to start the AsyncTask and have it provide an update via its onPostExecute() method. By calling Thread.sleep() you are sleeping the main thread (or UI thread) of your app, which is not good. You do not ever want to block the main thread. This article may help you better understand AsyncTask and threading in Android: http://po.st/Cei3m2
I don't think you should use a surrounding loop. Look at this example:
http://javatechig.com/android/progress-notification-in-android-example
the AsyncTask is a private inner class
the onPostExecute updates the UI with a message/cancels the load bar
This way you don't have to loop and the onCreate() can return instantly.
My App contains a function that takes time to load ( parsing files).
THe function is called at multiple user case, i.e. from multiple user triggered condition.
Besides, it is called when onCreate is called.
In simple word, the flow is:
User click/OnCreate trigger
Function to parse file
Post to windows
Other postprocessing
I hope the user can click cancel to stop parsing files.
I tried to use asynctask. I know I can put the function to onPostExecute.
But I assume onPostExecute is just for dismiss progress dialog. Or I have to move a lot of codes ( for different cases) to it. Not a good idea.
I do not suppose user to do anything during parsing files.
So, what is the best way to do so? Despite I know it is not good, I think i have to occupy the UI thread.
In simple word, I want to wait for "parsing files", but i do not want to occupy the UI thread, so user can click cancel.
update:
I tried. however, there is a problem:
I use asynctask. I called:
mTask = new YourAsyncTask().execute();
YourAsyncTask.get(); // this force to wait for YourAsyncTask to return.
DoSomethingBaseOnAsyncTaskResult();
YourAsyncTask.get() hold the UI thread. So, there is not loading dialog, and user cannot click cancel from the dialog. It seems I have to move every line after
mTask = new YourAsyncTask().execute();
to
OnPostExecute()
which i did not prefer to do so because DoSomethingBaseOnAsyncTaskResult() can be very different based on the return result. or else, it becomes do everything in YourAsyncTask()
AsyncTasks should ideally be used for short operations (a few seconds at the most.)
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time.This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
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.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
CODING
To start an Async task
mTask = new YourAsyncTask().execute();
and to cancel that task
mTask.cancel(true);
More detail is available here
In order to use the AsyncTask API, one has to follow the steps described below:
Create a class which extends AsyncTask.
Fill in the generic types available as generics in the class for:
the task execution array parameters
progress array parameters
result array parameters
Implement the method doInBackground(Parameters... parameters). This
method must execute the job which is supposed to be quite demanding.
Optionally, one can implement methods for:
cancelling the task - onCancelled(...)
executing tasks before the demanding task - onPreExecute(...)
reporting progress - onProgressUpdate(...)
executing activities after the demanding task is finished
-onPostExecute(...).
For the down voters,it would be better if you could provide a working solution,not every question need to have a code attached with it,if one is not clear with the concepts how can u expect him to provide you with the code he played with??
This is basically a conceptual question,i tried reading docs but still i couldn't get a better understanding of the topic. i am not sure how i should use async task....
i have used the async task before for displaying an image from internet,
but i am still confused how it works.I know 3 of its functions that are used commonly.
i.e
1.onPreExecute ()
2.doinBackground()
3.onPostExecute()
now i am confused that if i have to populate a list how should it be done??
I know The populating part should be done in the doinbackground(),but after that should i return the result (from the background),after the whole list has been populated, to
onPostExecute() and expect that the list will be loaded on the listview asynchronously
or should i return the result in parts(say a new item has been added to the list,send it to the onpostexecute immediately without waiting for the whole list to be generated, to be displayed and repeat the iteration ) to the onpostExecute()??and manage the lazy load ourselves by doing so?
well.. why don't you see this below android API information..
The 4 steps
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
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.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
onPreExecute() method is used when starting asynktask function.. typically in this method, someone use progress dialog..
and doInBackground() methos is used when progress dialog is running. in this method you can implement your job(function) that you want. I think this part is the most important point among methods of this asynktask class
and onPostExecute() method is typically used when finished background job.. in order to deliver some kind of data or result.. to View
I have a Async Task that creates a HashMap to create a Adapter to populate ListView. I have a progress dialog that shows during doInBackground method.In onPostExecute() method, I dismiss the progress dialog and call a method that populates my listview with the list of items saved in doInBackground method.
This works fine. But I noticed something strange:
The issue I see is, if I lock the screen when the progress dialog is about to be dismissed (in onPostExecute), the listview does not display, even though it has non-empty items in it. I verified it in logcat messages and when I debugged.
Is there a possibility that a screen lock (I do this my pressing power button once) blocking UI thread? How can I resolve the issue and make sure ListView displays its items?
Code for onResume():
#Override
protected void onResume(){
super.onResume();
if(MyAdapter !=null){
pull_listView.setAdapter(MyAdapter);//pull_listView is listview
MyAdapter.notifyDataSetChanged();//MyAdapter is the adapter
}
}
This situation illustrates the downside of using AsyncTask to do background processing. In some cases, an IntentService may be a better choice, especially if you think the background work is going to take some time. An AsyncTask ties the background work to the current Activity, while an IntentService is completely decoupled.
The Android training class Running in a Background Service shows you how to set up an IntentService, request work, and notify your Activity when the work is done. Passing data from the IntentService to the Activity is a bit more complicated, but there are options.
onStop() will be called when your screen goes out as per the Activity Lifecycle. You could override onStart() or onResume() and put a check in there to see if your data has been populated. If not, populate. You may even want to overide 'onStop()' to save data if the screen goes out.
Edit
In this particular situation, I would think onResume() or onStart() would be fine but onResume() is usually the safest because it is guaranteed to get called before the Activity is shown as illistrated in the link I gave. What kiind of a check you want to use is up to you and depends on how you handle evrything. However, if your AsyncTask is an inner class of your Activity class the you could simply create a boolean member variable, say boolean isDone=false; change this to true in your doInBackground() or onPostExecute() then your onResume() knows the data Is loaded. If its false then you can try to get data again. Hope this makes sense and can help