I need advice about ProgressDialog , I show dialog like
pd = ProgressDialog.show(
Dashboard.this,
"LOADING...",
"PLEASE WAIT", true, false);
and it shows, but it when in background is intensive calculation that circle stops to spin ( like it is blocked). I am running this code above inside onClick button. What to change to avoid this blocking or that is impossible ?
You have to move your intensive calculation to another Thread, to not block UI thread
see another SO question for example how to use AsyncTask and ProgressDialog together
progressDialog in AsyncTask
When you say your progress dialog does not spin, it actually means that your intensive calculation is blocking the main /UI thread
you should make use of an Asynctask
Also get a hang of painless threading in android
It will run in the background without causing hiccups in the UI thread...
Since android apps run on a single main (UI ) thread, you should avoid doing heavy tasks on the UI thread
An asynctask is basically an intelligent worker thread provided by the android system.. It contains helper methods wherein you can easily decide what you want to do
A progress dialog should be created in onPreExecute() and dismissed in onPostExecute()
Do intensive task in doInBackgound()
Here are some tutorials:
easy to understand asynctask
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 use a code that access HTTP service to receive login data, and before it, I tried to show a processing dialog, but it did not showed up. Then I tried to simply change the button label to tell the user to wait until data returns, but it also did not work. That's my code:
tryingToLoginDialog = ProgressDialog.show(this, "Por Favor Aguarde", "Efetuando Login...", true);
btn_Entrar.setText("Wait while logins...");
btn_Entrar.invalidate();
App.webService.Login(txtLogin.getText().toString(), txtSenha.getText().toString());
String LoginUserData = App.webService.getUserData(); /* this method freezes the app but do not crash it cause ThreadPolicy permit all*/
/* here some if's */
tryingToLoginDialog.dismiss();
btn_Entrar.setText("Login");
btn_Entrar.invalidate();
You should use AsynTask. This has 4 different method doInBackground() This method run in background(not in UI Thread) In your case you can do your networking stuff here and other three methods are onProgressUpdate(), onPostExecute() and onPreExecute() run in UI Thread So you can use these function to update GUI.
You were saying you want to show dialog so setup progressdialog in onPreExecute() and do your freezing stuff in doInBackground() and use other method according to your need.
See detail here
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.