Let's say we have two buttons, each with a OnClickListener. Each of listeners show a ProgressDialog and do some background work. (Behind the scene is an AsyncTask, the dialog is opened in onPreExecute. I don't think it matters, just for the record...). Let's say there is some rule saying no more than one background worker may be active at any given time.
My assumption was that the Dialog prevents two background workers running at the same time. I thought the modal dialog blocks the UI and it's not possible to click another button after the show() method of the dialog is called. I was wrong.
If you click the buttons fast enough, it's possible to trigger both background workers (almost) at the same time. The log shows that it's possible to click two Buttons within a 150 ms time span despite the Dialog:
04-14 18:34:04.390: DEBUG/greenrobot(1860): Clicked: 2131034112
04-14 18:34:04.470: DEBUG/greenrobot(1860): doInBackground2: 2131034112
04-14 18:34:04.540: DEBUG/greenrobot(1860): Clicked: 2131034113
04-14 18:34:04.570: DEBUG/greenrobot(1860): doInBackground2: 2131034113
The dialog code looks like this:
progressDialog = new ProgressDialog(currentActivity);
progressDialog.setMessage(msg);
progressDialog.show();
What did I miss? I hope I missed something really stupid, because if not, I cannot think of a nice and solution preventing UI interaction after the click. Synchronizing the background workers is not a solution because the UI and scenario is more complex.
Disable the button after it is clicked, until it is safe to be clicked again.
show() is asynchronous. The dialog will not appear immediately upon the call to show(). It will occur moments later.
Related
I have an AsyncTask class that handles all networking calls for my app. I also have a Globals class that holds a progress dialog. Now, what I want is for there to only be one progress dialog at a time; this is fairly simple. The Globals class initializes the dialog, and each time it is used by the AsyncTask, only the message is changed. My issue is determining when to dismiss it. If I use p.dismiss() at the end of onPostExecute(), then the progress bar will go away until the next AsyncTask runs, which is not what I want. However, if I don't include the line there, then the progress dialog will stay up indefinitely. I guess what I'm trying to find is a way to see if all AsyncTasks have finished running. By doing this, then that one global progressdialog will be able to close without looking wonky.
Chaining together all the AsyncTasks is not an option (e.g. having the first one execute the second in its onPostExecute()).
Also note that there could be anywhere between one and five AsyncTasks running at the same time.
How can I determine if every AsyncTask is complete?
you could keep track of how many you are starting and create a callback to the class every time a task finishes, then when the returned count matches the start count you know all the tasks are done.
there really is no way to know when see what tasks are running without doing some thing like that.
there is a getStatus but you would have to keep polling for the status to see if the individual task is done or not
I am creating an app MainActivity that can calculate a report from its database to be shown in ReportActivity. All report calculation is done in ReportActivity.onCreate().
When the user click on MainActivity-s menu "generate report" the menĂ¼ remains open for 2 secs until ReportActivity.onCreate() has finished and the report becomes visible.
What is the easiest way to give the user some visual feedback?
I already found ProgressDialog onCreate that shows a progressdialog while doing all calculation in an AsyncTask.
I wonder if there is some easier way to give the user some visual feedbak that the menue was successfully clicked and that the device has not crashed.
in ms windows i would use a waitcursor (hour-glass)
I already tried to open a ProgressDialog() in oncreate of the ReportActivity
final ProgressDialog progressDialog = ProgressDialog.show(this, "MY Dialog", "Please wait...");
but it is not shown at all.
Update final solution:
As the answerss suggested I implemented an AsyncTask for the processing following this tutorial
based on this codesample
You need to move your long-running code into a background thread. Long-running code on the UI thread will lock up the UI, which causes the user to think the app is frozen/crashing. Look into using AsyncTask. This allows you to run a process on a background thread and also give visual feedback to let the user know that your app is working.
Design a layout with ProgressDialog. Use setContentView(Progressdialog). Count time for 2-4 seconds (you choice) again set your older layout in setContentView. Why don't you use AsyncTask?
Use a bar or circle activity indicator. From the official design guide:
Activity indicators are for operations of an indeterminate length.
They ask users to wait a moment while something finishes up, without
getting into specifics about what's happening behind the scenes.
I've got an app that uses ListActivity to give users a list of actions. When they click one I use an Intent to launch a separate activity.
My problem is that the actions that the app performs take about 20 seconds to finish, and since I don't want the user to receive that nasty ANR dialog, I tried to use AsyncTask to present them with a loading screen in the mean time. I tried using setContentView(R.layout.loading); on onPreExecute(), but it throws a NullPointerException which as far as I have figured out is due to the fact that loading.xml is not "a ListView whose ID is android.R.id.list".
So what can I do now? How can I show that loading screen? Is there a way around this pretty annoying situation? Any help would be greatly appreciated. Thanks!
I am not sure exactly what your use case is; you have a list of items that are populated immediately, and upon selecting one an action is taken? The action that is taken is to launch another Activity which performs background processing?
Or does it take that long to populate the list of actions?
If the former, you can use an AsyncTask for the long-running activity instead of an Intent to launch another Activity: in the callback you get for the click on the item in question, you would create the AsyncTask, and in doInBackground you would perform the long-running activity, with onPostExecute refreshing or manipulating your list as necessary.
Another thing to consider is using a dialog box to show a loading screen, if the loading is required to happen before you launch a new Activity.
If you can further describe your use case, I can help you more.
It's not the loading screen you need to have on the AsyncTask, it's that 20-second Activity initialization. I would look for a way to do all the setup in a background thread in a Service while the user is free to merrily bop around in other Activities. I'd try hard to find a way not to just stall the user for 20 seconds. Maybe take them to the target Activity and show them data cached from their last visit until the new set is ready.
Fire up and display your loading dialogs in your onCreate() of the Activity being called, then call Dialog.dismiss() in your AsyncTask's onPostExecute().
I have a button in my application. When I clicked the button I am starting some function using thread. When the thread is running I don't want any of my view get focus (including tab also). How can I make the whole application unfocusable/untouchable till the thread completes its working?
You should show a ProgressDialog. If you don't do so, the user will think that your app is frozen. You can use the setCancelabel(false) method in order to prevent user from closing the dialog.
I have an activity with in which there is a async task that will do some download stuff. AT the time of downlaoding it will show a loading dialog.
My problem is, it worked fine for me when me doing it in only one orentiaon. But when i rotate at the time of download, it shows window leaked and will crash at the
dialog.cancel in my post excute.
From my study on it more i understood it due the change in the context when device is rotated.
That is when a device is rotated the activity will be recreated so the context will be changed.
But i have created the dialog with old one and that wasn't the current context. So when i cancel it it shows error
What is the solution for this, any idea frnds.
Me using honeycomb, me tried but with fragment but didnt get a good sample for that. Me now mainly trying that,
if anyone can give me some links for that it will be
great
First of all: open your dialog using the showDialog method (there are a lot of examples in the official documentation). If you do so, the activity will take care of dismissing the dialog on destroy, and re-showing it after the activity has been recreated.
Also... if the dialog shows a progress bar (not a wheel), you will want to update the progress of the dialog after orientation changes. In order to do so, I recommend to use the onRetainNonConfigurationInstance to return the current state of the dialog and/or the activity itself. Then, you can use getLastNonConfigurationInstance to recover that state. Google about those two methods if you want to see examples.
Another thing to keep in mind: if you are updating the state of the dialog an/or any other UI element from the AsyncTask, you must be aware that after the activity is recreated, the AsyncTask may be pointing to the wrong UI references. In order to handle this, you can create a proxy class (Proxy design pattern) to detach the AsyncTask progress notifications from the current UI elements.