Before I'm lampooned, for blocking the main UI thread, here is the scenario:
A Service runs once a day - takes around 15 secs to complete. Heavy database transactions
By coincidence the user starts the app during that time
The home screen loads data from the database
But because the database is locked (step 1), this throws an error.
So I need to FREEZE the UI thread till the service is completed. No AsyncTask because the UI will continue to execute and throw an error. I've managed to put the "onResume" function to sleep till the service finishes. But during that time I'm unable to show any dialogs telling the user to wait or any progress bar telling the user to sit tight.
If I try
start onResume
if (service is running?)
show progress dialog
while the service is running, thread.sleep
dismiss progress dialog
end onResume
The thread sleeps fine and wakes up great. But the damn progress dialog doesn't show till onResume...resumes! Bottom line, how do I show an indicator (progressdialog or dialog) before I put the main thread to sleep?
I'm open to solutions that load another activity till the service resumes. I've tried that, but the previous activity continues on happily :|
You can not show a progress dialog if you are blocking the UI thread.
I guess you want to invoke the dialogue in onResume, but the UI won't start to show the dialog before onResume and onPaused are done. But as you are blocking the UI thread in OnResume this will not be reached until the blocking is over. Therefor its not possible.
You need to put the waiting in an async task and callback to your UI thread when done.
Good would be to take a loading-activity that starts your actual activity when the DB update is finished.
Related
in my activity, i have an asynctask that downloads a series of images...(it may take some time depending on the size of the images)... before i execute the asynctask, i display a progress dialog in onPreExecute and a notification (when user clicks on notification it is redirected to my activity with the progress dialog). when my asynctask completes, in onPostExecute, i remove the dialog and the notification.. i handle screen orientation by using onRetainNonConfigurationInstanceto save my asynctask so that when screen is rotated, i check if task is still running and i display the progress dialog if it is still running in onCreate
Problem : sometimes: my asynctask downloads only 1 file and it seems that it gets killed...(no exception in logcat)... as a result, my notication is always there and my progress dialog also... and they remain there indefinitely....
i have tried the solution by Jeff Axelrod there: How can I ensure an AsyncTask is completed before my activity is killed?:
It looks like if I override the onPause() event in my activity, and from within the overridden onPause(), I call cancel(false) on the AsyncTasks, then the activity is not destroyed until the AsyncTasks are completed.
seems to do the trick but problem is that my onPostExecute is not called anymore; all images download fine but as onPostExecute is not executed, notification and progress dialog still remain there forever.
waiting for your solutions guys! i read use asyntask only for short task; will the use of thread and handler solves my problem? will android kills my activity or thread if the latter is not finished??
Best way how to handle Asynctask is described in this article.
In short, the idea is to keep AsyncTask in fragment with setRetainInstance(true); these will keep You AsyncTask alive all time user is in activity holding this fragment and won't be destroyed on configuration change (orientation change).
If You need Your AsyncTask to run after user leaves Activity, for example goes to next Activity but You wish download to continue You should use services.
I have an Android App that uses an RPC mechanism to set/get information to/from a server. I call the RPCs from whithin the main thread (blocking) and I want them to be blocking. However, sometimes a call can last for some seconds and I'd like to display an indeterminate progress dialog after some specified time (e.g. 1 second).
I tried to spawn a new thread that makes the call and the main thread waits in a loop (with sleeps) until the call has been finished. Inside this loope I show the progress dialog but this is not working.
Is it possible to show and update the progress dialog inside another Thread or does anybody know a better solution that allows me to use blocking calls?
You cannot do both, make the main thread wait in a loop and show a progress dialog, at the same time. Either the main thread waits or shows the dialog.
Why do you want to block the main thread? Communication over the internet should always be done in a background thread because you never know how long it will take to complete. Do that stuff in AsyncTask and show the progress dialog in main.
Try using AsyncTask. It is an android mechanism which is used to make such network calls. Get the brief detailing of AsyncTask here:
Using AsynTask to show progress bar while attempting to SSH to Server
Using a AsyncTask you can block the user from proceeding ahead. You have to show a progress dialog in the onPreExecute() method of the AsyncTask. All your network related activities will take place in doInBackground(). After the background action is completed there will be a call to onPostExecute() where the progress dialog will be dismissed.
AsyncTask is a asynchronous call because you have 2 threads working simultaneously, one is the UI thread on which you are showing your progress dialog and the other is the non-ui background thread which is fetching your data from the server.
Hope this explanation helps.
I have found a solution that seems to work (at least I havent noticed any problems yet). I know the proper way would be to use somethn like AsyncTask but in my case I have no benefit from it and it complicates the program logic.
To update the UI within a new thread:
new Thread()
{
public void run()
{
Looper.prepare();
... do UI stuff here
Looper.loop();
}
}.start();
I have the following structure:
in UIActivity1:
MyMyProgressDialogFragment progressDialog = MyMyProgressDialogFragment.newInstance();
progressDialog.show(getFragmentManager(),"dialog");
getFragmentManager().executePendingTransactions();
..do some heavy work and send messages to progressDialog
The DialogFragment gets created and the ProgressBar in this fragment starts spinning.
But when I now start the heavy work in the activity which created the dialog fragment the progress bar within the fragment stops.
When reading through the fragment doc I understand that a fragment has its own activity - same as the Ui Activity1. And afaik each activity runs in a separate thread.
So why does the progressbar in the dialog fragment stop when the UIActivity1 starts with its heavy work?
Shouldn't they be independant?
ps when I run the heavy work outside the UIActivity in a different task again, the progress bar keeps spinning without problems.
Where is my mistake in understanding here?
Thanks!
Its not clear from the information you have shared, however looks like you are doing all your heavy execution in your UI Thread. That is the activity's main thread. Whether the activity you spin off with your fragment is meant to do just this work is irrelevant, the UI thread has to be used only to update the UI elements and generally avoid tasks that take longer than 100 - 200 ms. This is as per android Non-Responsive Application documentation. This is probably the problem, any long standing or long executing tasks have to be done in a background thread.
Take a look at this example of using the progressbar in Android.
I have a long task that requires 10 / 15 seconds. I want to display a dialog, or a view or other stuff to let the user know "hei! I'm working for you. I'm at 90%".
Actually I have 3 layouts: the currentLayout, the progressLayout and the resultLayout. From the main activity I have a function like that:
...
setContentView(R.layout.progressLayout );
SomeLongTask();
setContentView(R.layout.resultLayout);
...
but the progressLayout never shows.
What's the best way to do this?
You are starting the long Task in your User Interface Thread. This thread is also responsible for redrawing the UI and acting on Input Events. If you make a blocking call to the long task function your UI Thread will be busy to do the task and the User Interface can not change. The Android System even will think your Application crashed because it is not reacting to user input anymore.
You have to start the task in an AsyncTask and do all the heavy work in the doInBackground method and update your UI in the onPostExecute method. That way the UI Thread will start the task and then return to updating the Interface and acting on User Events.
I have a comment activity that loads a Thread and sends some data to a server; the activity is immediately finished once the submit button is pressed.
The user is then free to do other things in my application.
When the server responds an AlertDialog is shown.
The problem is that since the initial context has been destroyed, my application crashes.
I tried getApplicationContext() but still get an exception.
Put your network stuff in a Service, then show a status bar notification instead of a dialog.
Take a look at AsyncTask
From JavaDocs:
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.