Updating progress dialog in Activity from AsyncTask - android

In my app I am doing some intense work in AsyncTask as suggested by Android tutorials and showing a ProgressDialog in my main my activity:
dialog = ProgressDialog.show(MyActivity.this, "title", "text");
new MyTask().execute(request);
where then later in MyTask I post results back to activity:
class MyTask extends AsyncTask<Request, Void, Result> {
#Override protected Result doInBackground(Request... params) {
// do some intense work here and return result
}
#Override protected void onPostExecute(Result res) {
postResult(res);
}
}
and on result posting, in main activity I hide the dialog:
protected void postResult( Result res ) {
dialog.dismiss();
// do something more here with result...
}
So everything is working fine here, but I would like to somehow to update the progress dialog to able to show the user some real progress instead just of dummy "Please wait..." message. Can I somehow access the progress dialog from MyTask.doInBackground, where all work is done?
As I understand it is running as separate Thread, so I cannot "talk" to main activity from there and that is why I use onPostExecute to push the result back to it. But the problem is that onPostExecute is called only when all work is already done and I would like to update progress the dialog in the middle of doing something.
Any tips how to do this?

AsyncTask has method onProgressUpdate(Integer...) that you can call each iteration for example or each time a progress is done during doInBackground() by calling publishProgress().
Refer to the docs for more details

you can update from AsyncTask's method onProgressUpdate(YOUR_PROGRESS) that can be invoked from doInBackground method by calling publishProgress(YOUR_PROGRESS)
the data type of YOUR_PROGRESS can be defined from AsyncTask<Int, YOUR_PROGRESS_DATA_TYPE, Long>

Related

Android: Asynctask without showing dialog

I've searched in the web but I only find cases where the users want to show the dialog in the asynctask like this example: protected void onPreExecute().
{
super.onPreExecute();
pDialog = new ProgressDialog(NumericoComercial.this);
pDialog.setMessage("Actualizando ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
What I would like to know is if it can be done an asynctask without showing any dialog in onPreExecute() and onPostExecute() as usually is done.
I have experienced some problems using asynctask with dialogs regarding Window Leaked Error. The thing I've tried is not adding any dialog to the Pre and Post Actions like the following example.
class UpdateCandidatos extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
}
protected void onPostExecute(String file_url) {
}
}
Could be any errors using this method, for example when the activity is finished?
Thank you
onPreExecute() and onPostExecute() are not required methods extending Aynctask then all the things you write in those methods (Dialog, ProgressDialog etc) are unnecessary for the correct working of your class.
class UpdateCandidatos extends AsyncTask<String, String, String> {
protected Long doInBackground(String... urls) {
//add here your background work
}
}
this is a very simplified and fully forking AsyncTask that do "something" in background showing no dialog.
Note: you will have to handle the task according to the lifecycle of your app
I would recommend that you cancel your async task in you onPause() method. This way if your activity closes, the async task wont try to publish any data, and onPostExecute wont be called.
Hm, you shouldn't be having any errors with onPostExecute(), you can use async task without showing any data, its not mandatory. You dont even have to #override that function, just put Void i the declaration ( ...extends AsyncTask<...,...,Void> )

Cancelling an asynctask with back button

I am trying to do some tasks in background with AsynTask. As below:
class CheckTypesTask extends AsyncTask<Void, Void, Void> {
ProgressDialog Asycdialog = new ProgressDialog(Home.this);
String typeStatus;
#Override
protected void onPreExecute() {
super.onPreExecute();
Asycdialog.setMessage("First time initialization. Please wait...");
Asycdialog.show();
}
#Override
protected Void doInBackground(Void... arg0) {
create_database_and_tables();
insert_in_questions();
insert_in_answer_option();
return null;
}
#Override
protected void onPostExecute(Void result) {
// hide the dialog
super.onPostExecute(result);
database.close();
Asycdialog.dismiss();
}
Now the problem is that, if i press the hard back key while ProgressDialog is visible, it simply just closes the ProgressDialog. But when i check the Database, i find that all of my records which are to be inserted, are inserted successfully. I dont understand why the ProgressDialog keeps on showing even if the doInBackground() finishes its work, no matter the ProgressDialog disappears after sometime, but why is it so ??
My next question is that, if the data set that is to be inserted is not big enough, then why ProgressDialogstill appears. Actually, i tested like this. I pressed the hard back key immediately after two seconds. And checked the database, I found that all the records were inserted. Why onPostExecute() is not called as soon as the doInBackground() finishes its work ??
And the last question is, i want to show an AlertDialog with yes and no Button, when hard back key is pressed while ProgressDialog is still visible. Then if, yes is pressed the ProgressDialog should disappear and the doInBackground() work should be stopped. And if no is pressed, then only the AlertDialog should be dismissed, and the ProgressDialog should still be visible.
Please help me solving my doubts.
If you place some line of code in doInBackground that only executed once and not in loop,there is no way to cancel it after executing your task.But if you have loop in it or other commands that run periodically,you can use setCancel(true) for your task and check the value of isCanceled() of task before doing your statement in loop.
I guess that when you close dialog,it takes some times to check DB records and during this timedoInBackground continues until all records inserted in DB.So when you check your DB,see all records are inserted.
Also onPostExecute() immediately being invoked on the UI thread after doInBackground(Object[]) returns(if task was not canceled).For example execute this AsyncTask:
class Test extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
System.out.println("End doInBackground");
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
System.out.println("Start onPostExecute");
}
}
But you added some commands before dismissing dialog that may consumes little times and also Activity transitions(dismissing dialog and foregrounding Activity) consumes some times itself.
Edit:
And the last question is, i want to show an AlertDialog with yes and
no Button,...
You have to add a method to your AsyncTask class that shows an alert dialog with desired functionality and store a reference to task and also override onBackPressed() method of Activity.When onBackPressed() executed,call that method of Task instance.Although you know you can not cancel inserting progress in this way.If you want that no record insert to DB,you can remove them in background, after they inserted!!

Android How To Properly Notify Data Set Changed for ListView

I am trying to update my list and display the updated list in my activity. Every time I do so I get the following error
The content of the adapter has changed but ListView did not receive a notification.
Make sure the content of your adapter is not modified from a background thread,
but only from the UI thread.
Here is my code, I am using an AsyncTask to achieve this task. I call notifyDataSetChanged() on my adapter but it does not seem to work. What am I doing wrong?
class MyTask extends AsyncTask<Context, Integer, String> {
#Override
protected String doInBackground(Context... params) {
GregorianCalendar currentDateclone = (GregorianCalendar) currentDate.clone();
ListPopulater2.listPopulate(currentDateclone, 7, items, Id);
//method to update list info
}
// -- gets called just before thread begins
#Override
protected void onPreExecute() {
progressdialog = ProgressDialog.show(SectionListExampleActivity.this, "", "Loading..."); //display progress bar
super.onPreExecute();
}
// -- called as soon as doInBackground method completes
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.d("postExecute", "here");
adapter.notifyDataSetChanged();
progressdialog.cancel();
}
}
Try moving:
ListPopulater2.listPopulate(currentDateclone, 7, items, Id);
to your onPostExecute.
The reason that this worked is because you need to update the list after you've completed all your background activity, not while you are doing it. You can use the onProgressUpdate, but that is for your progress dialog. Updating you list view should be done after you have all you data, otherwise, you will get the error you did because the UI runs on the main thread, and you are trying to update it with the background thread.
As for the progress dialog, there is a purpose. If you are doing something that is going to take awhile to complete, the dialog will tell the user how close you are to completing the background task.
Hope that makes sense.
When Ever you want to do something which deal with the UI you have to do that task in UI thread.
So for this you can use 2 approach:
use runOnUi() method
Use OnPostExecute() method
And you have to use notifyDatasetchanged() at that place where you are setting adapter in listView.

Progress Dialog on open activity

I have a problem with progress dialog on opening an activity (called activity 2 in example).
The activity 2 has a lot of code to execute in this OnCreate event.
final ProgressDialog myProgressDialog = ProgressDialog.show(MyApp.this,getString(R.string.lstAppWait), getString(R.string.lstAppLoading), true);
new Thread() {
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
showApps();
}
});
myProgressDialog.dismiss();
}
}.start();
The showApps function launch activity 2.
If I execute this code on my button click event on activity 1, I see the progress, but she doesn't move and afeter I have a black screen during 2 or 3 seconds the time for android to show the activity.
If I execute this code in the OnCreate of Activity2 and if I replace the showApps by the code on OnCreate, Activity1 freeze 2 seconds, I don't see the progress dialog, and freeze again 2 seconds on activity 2 before seeing the result.
I had the same issue and using an AsyncTask is working for me.
There are 3 important methods to override in AsyncTask.
doInBackground : this is where the meat of your background
processing will occur.
onPreExecute : show your ProgressDialog here ( showDialog )
onPostExecute : hide your ProgressDialog here ( removeDialog or dismissDialog
)
If you make your AsyncTask subclass as an inner class of your activity, then you can call the framework methods showDialog, dismissDialog, and removeDialog from within your AsyncActivity.
Here's a sample implementation of AsyncTask:
class LoginProgressTask extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
try {
Thread.sleep(4000); // Do your real work here
} catch (InterruptedException e) {
e.printStackTrace();
}
return Boolean.TRUE; // Return your real result here
}
#Override
protected void onPreExecute() {
showDialog(AUTHORIZING_DIALOG);
}
#Override
protected void onPostExecute(Boolean result) {
// result is the value returned from doInBackground
removeDialog(AUTHORIZING_DIALOG);
Intent i = new Intent(HelloAndroid.this, LandingActivity.class);
startActivity(i);
}
}
AFAIK you cannot preload any activity with progress dialog displayed. Are you testing on a real device or in emulator?
I've seen workarounds that opened an activity with a ViewFlipper having a progress animation in the center, and in the next View, it was loaded an activity, but it's not something is recommended and hard to implement to work as you wish.
GeeXor
I would suggest you to avoid performing lots of operations in Activity 2's OnCreate.Writing lots of operations in OnCreate is a reason for the black screen between activities.So perform those operations asynchronously using AsyncTask or in a Thread (or write them in onStart if they are unavoidable).
The other suggestion is to start another progressDialog in activity 2's onCreate which will run until all of your data is loaded & user will know that something is happening in background.
this is what i would do. create a handler on the ui thread, start the background processing thread and then show the progressdialog. when the background thread has finished it's work get it to post a runnable on the ui thread via the handler to dismiss the dialog.

Android ASync task ProgressDialog isn't showing until background thread finishes

I've got an Android activity which grabs an RSS feed from a URL, and uses the SAX parser to stick each item from the XML into an array. This all works fine but, as expected, takes a bit of time, so I want to use AsyncActivity to do it in the background. My code is as follows:
class AddTask extends AsyncTask<Void, Item, Void> {
protected void onPreExecute() {
pDialog = ProgressDialog.show(MyActivity.this,"Please wait...", "Retrieving data ...", true);
}
protected Void doInBackground(Void... unused) {
items = parser.getItems();
for (Item it : items) {
publishProgress(it);
}
return(null);
}
protected void onProgressUpdate(Item... item) {
adapter.add(item[0]);
}
protected void onPostExecute(Void unused) {
pDialog.dismiss();
}
}
Which I call in onCreate() with
new AddTask().execute();
The line items = parser.getItems() works fine - items being the arraylist containing each item from the XML. The problem I'm facing is that on starting the activity, the ProgressDialog which i create in onPreExecute() isn't displayed until after the doInBackground() method has finished. i.e. I get a black screen, a long pause, then a completely populated list with the items in. Why is this happening? Why isn't the UI drawing, the ProgressDialog showing, the parser getting the items and incrementally adding them to the list, then the ProgressDialog dismissing?
I suspect something is blocking your UI thread after you execute the task. For example, I have seen folks do things like this:
MyTask myTask = new MyTask();
TaskParams params = new TaskParams();
myTask.execute(params);
myTask.get(5000, TimeUnit.MILLISECONDS);
The get invocation here is going to block the UI thread (which presumably is spinning off the task here...) which will prevent any UI related stuff in your task's onPreExecute() method until the task actually completes. Whoops! Hope this helps.
This works for me
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(viewContacts.this);
dialog.setMessage(getString(R.string.please_wait_while_loading));
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
It is because you used AsyncTask.get() that blocks the UI thread "Waits if necessary for the computation to complete, and then retrieves its result.".
The right way to do it is to pass Activity instance to your AsyncTask by constructor, and finish whatever you want to do in AsyncTask.onPostExecution().
If you subclass the AsyncTask in your actual Activity, you can use the onPostExecute method to assign the result of the background work to a member of your calling class.
The result is passed as a parameter in this method, if specified as the third generic type.
This way, your UI Thread won't be blocked as mentioned above. You have to take care of any subsequent usage of the result outside the subclass though, as the background thread could still be running and your member wouldn't have the new value.

Categories

Resources