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();
Related
I need some work to be done on the UI thread, but this means I can't also (that I know of) display a ProgressBar as the UI is busy executing other tasks.
I know this sounds a bit illogical, but is there a way to display an indefinite ProgressBar on the UI thread while the UI thread is busy?
I am aware of using Runnables and AsyncTasks, I'd use them to complete the actual work if I could, but can these be used for displaying the ProgressBar itself?
Just show a textview with Loading... in it, or some other static view (imageview with progress, that doesnt spin). Any other solution will need to do the work on the UI.
I would really check my code in order to free the UI because the if u use the UI for too long the user wouldnt be able to press back or anything and he will feel as the the app is stuck.
The short answer is no.
If your UI thread block due to heavy work, the UI does not get updated.
But I am sure you can improve you code so that it does not block the UI thread.
Yes, you can display an indefinite ProgressBar on the UI thread with the help of AsyncTask.
onPreExecute() {
// Display Progressbar here
}
doInBackground() {
// Do some heavy task here, but not related to UI thread
}
onPostExecute() {
// Dismiss the Progressbar
}
my AsyncTask should wait till event in the UI-thread happen.
so, I started to have simple while loop. However, in some of the devices that caused the UI thread to freeze. so after reading the following answer:
Fatal Spin-On-Suspend/Stuck on ThreadID
[However, it is not quite the same - i put the while in the async-task not in main-activity]
I added Thread.sleep - and it seem to indeed solve the problem.
However, I feel like I'm doing something wrong here...I wonder what is the right way to do it.
Do not ever sleep or block the UI thread. Wait in the background thread of the AsyncTask.
One way is as suitianshi is pointing out with wait()/notifyAll(). Another one is to use a CountDownLatch:
In the UI thread create a latch: CountDownLatch latch = new CountDownLatch(1);
Subclass AsyncTask so that it takes a latch in the constructor and save it to a reference mLatch
in doInBackground(), when you need to wait call mLatch.await(). This will block the AsyncTask
in the UI, when the event you're waiting happens, call latch.countDown()
You should be good to go from here.
My opinion is going to be different...
my AsyncTask should wait till event in the UI-thread happen.
AsyncTask's are great for long running operations like http downloads, long i/o operations, image resizing, or any cpu intensive operation that would freeze the UI thread.
However, Android runs AsyncTasks sequentially and not in a pool by default. More details here.
So if you have an AsyncTask that runs indefinitely, such as waiting for a UI action, you could likely block other AsyncTasks from running. Leading to more deadlock and threading problems.
I would suggest any of the following:
Use a different Executor for your AsyncTask so it runs similarly as it does today, but not to conflict with other AsyncTask items. This is the easiest approach.
Split your AsyncTask up into multiple tasks. The first one does whatever your current AsyncTask does up until the wait. The second one does whatever your current one does after the UI event. The latter task gets queued by the UI that generated the event.
Use a dedicated Thread. Use the Handler class to marshall events back from the thread to the UI thread as appropriate.
AsyncTask is introduced for running things which takes long time. In earlier android OS, it can be done in main thread or UI thread. But now android forces us to do long running things in AsyncTask to make UI thread responsive. If you want during AsyncTask your android UI do nothing then you can simply add progress Dialog during it. Start progress Dialog in onPreExecute() & end it in onPostExecute(String[] result).
Sample code : in AsyncTask
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(MainActivity.this);
dialog.setMessage("Loading, please wait...");
dialog.setIndeterminate(true);
dialog.show();
}
#Override
protected void onPostExecute(String[] result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
// do something with result
}
Thanks
I am working on an app where i do some calls in synchronized manner using the
class HttpUtil extends AsyncTask<Void,Void,String>
{...}
HttpUtil httpUtil = new HttpUtil();
httpUtil.execute((Void[]) null).get();
This will call to a AsyncTask method.
Issue:
The spinning wheel is not shown in the UI since we do a UI blocked request. Even if I add a toast then the toast is displayed after the request is completed.
If I make asynchronous calls then I get the spinning wheel as the UI was not blocked
Expected:
I need to show a spinning wheel for the blocked request(done adding get() method) also.
Do not use get() on a network operation. Just don't. Your app will freeze, and either get killed by the system, or the user will be frustrated that your app blocks the entire UI of the system. It's absolutely unacceptable, and there is no reason why a well-designed app should need to resort to that.
You turn on your indeterminate progress in the AsyncTask's onPreExecute(), and turn it off in onPostExecute(). These two methods are always run on the UI threat. Please refer to the documentation for AsyncTask.
Further, you won't need to pass Void[] null to the execute() call -- just pass nothing, which will result in an empty array of Void.
If any other operations or UI updates depend on the result of the request, then do those updates in onPostExecute. If you want to create modality to essentially "halt" the UI while the request is running, then display a dialog box, but please provide a cancel option.
i am making lot of HTTP calls in my applications & switches between the views, now i'm handling the Http calls in a thread, but i want to make user to wait when the http request in progress. How to do this?. I just need to show a wait cursor or loading string.
You can use a ProgressDialog whit a Handler.
Android Progress Dialog Example
Android's indeterminate ProgressDialog tutorial
Cheers
I find the name a bit misleading, but you should show a ProgressBar while background operations conclude.
May be this will helpful. You have to make a background operation using thread concept like AsyncTask. Using this you can hide the actual work from the UI part. And AsyncTask will get unallocated after your operations are completed.
Create a subclass of AsyncTask
Use AsyncTask to do background work
Call onPreExecute() to initialize task
Use a progressbar with setIndeterminate(true) to enable the indeterminate mode
Call onProgressUpdate() to animate your progressbar to let the user know some work is being done
Use incrementProgressBy() for increment progressbar content by a specific value
Call doInBackground()and do the background work here
Catch an InterruptedException object to find end of background operation
Call onPostExecute() to denote the end of operation and show the result
I am creating an AlertDialog using an AlertDialog.Builder and showing it. After showing it, I need to pause application until the user comfirms the Dialog.
I exactly need to pause in a method showing Dialog thread, because its calling method throws a fatal error after return.
Is there any way to do that?
In Android, you can't pause the UI-Thread, as it will result in the OS showing the Application is not responding dialog after about 5 seconds of being paused.
Also, as mentioned by CommonsWare in the comments, Dialogs don't operate in a separate thread.
Without seeing your code it's a bit difficult to answer, but what I could suggest right now is place all the code you need to "pause" in an AsyncTask.
You can place all the code before the pause in the onPreExecute() method, than show your dialog, and in the doInBackground() method, maybe in a while loop or something with volatile variables or something (this code runs on a background thread so it won't stuck the UI-Thread) and then the code after the pause in the onPostExecute() method.
both onPreExecute() and onPostExecute() operates on the UI-Thread. the onPost is called after the doInBackground has finished.
But again, if you'd show some code of the pause it would be easier to help you.
Further reading: AsyncTask
Another way to handle this is to use threads. In a non-UI thread, call your AlertDialog's show() method using the runOnUiThread() method of your Activity. Call Object.wait() in your non-UI thread, and call Object.notifyAll() in your AlertDialog's OnClickListener. The non-UI thread will then wait until the user clicks on your AlertDialog.