I need to do some work on the UI thread, specifically setting up some views, etc. - this can't be done in a background thread. The process is invoked on a button click and takes about a second or so to complete - without a progress dialog it looks as if the app is frozen. I use progress dialog with AsynTasks in several places and it works fine - however here I'm struggling.
I started with simple:
showDialog(DIALOG_PLEASE_WAIT);
viewInfo.setFromGuide(true); //this method just sets a variable
viewInfo.setVenue(venue); //this method does a lot of UI manipulation and takes a second or so
showScreen(VIEW_INFO); //this method shows the corresponding view in ViewFlipper
dismissDialog(DIALOG_PLEASE_WAIT);
However the dialog would not show (sort of expected, as this is all on UI thread.
Then I changed the code to this:
Handler hnd = new Handler() {
#Override
handleMessage(Message m) {
viewInfo.setFromGuide(true);
viewInfo.setVenue(venue);
showScreen(VIEW_INFO);
dismissDialog(DIALOG_PLEASE_WAIT);
}
}
showDialog(DIALOG_PLEASE_WAIT);
new Thread() {
public void run() {
hnd.sendEmptyMessage(0);
}
}.start();
This still doesn't show the dialog - naturally, the UI work in handleMessage is still done on the UI thread. So, what can I do to show the progress dialog?
If it takes really takes a second or so to complete than maybe you can just use a simple Toast notification with a message like "Please wait"
as you are using AsyncTask you can override onProgressUpdate which is called when ever you call publishProgress() from inside the doInBackGround so you can publish your results smoothly while working in background because, onProgressUpdate works on the UI thread.
Related
I have a web service request in my Android app which might take a second or two to run. I have an event handler which fires when it completes. I am trying to show a dialog to show the progress of this request.
So far I have this:
var progressDialog = Android.App.ProgressDialog.Show(this.Activity, "Please wait...", "Communicating with server...", true);
new Thread(new ThreadStart(delegate {
WCFClient WCF = WCFService();
WCF.TestCompleted+= TestCompleted;
WCF.TestAsync(GetID());
progressDialog.Dismiss();}
)
).Start();
The problem is obvious, the dialog displays and disappears in a flash. I am declaring var progressDialog in the UI thread. How can I reference it again in an event handler?
I would normally use RunOnUIThread but I cannot target "progressDialog" that way as it does not exist in my layout.
It seems like this should be easy - am I missing something in my approach?
There are a few issues with your code. The first is there is a memory leak. You are holding onto the progress dialog in your thread. If the user rotates the device, your Activity will be killed but the garbage collector won't be able to garbage collect the reference because your Thread is holding onto it.
Secondly, you cannot update the UI from another thread, you have to update on the UI thread.
You need to use a Handler, pass a reference to the other threads (in the constructor), then when needed send a message to UIthread to dismiss the progress dialog.
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (progressDialog.isShowing()) progressDialog.dismiss();
}
};
in the thread, do this:
mHandler.obtainMessage().sendToTarget();
Also there is another issue in the code, you don't seem to check if you completed the task, BEFORE dismissing the dialog.
I want it to show up as soon as I click the login button, but it only shows after the loggin process has finished
What am i doing wrong
runOnUiThread(new Runnable() {
public void run() {
mProgress.setVisibility(View.VISIBLE);
}
});
doLogin();
mProgress.setVisibility(View.INVISIBLE);
Since you are using another thread to show the Visibility, the runnable might get scheduled any time in the future. That is the reason it is being shown late.
Maybe adding a sleep routine in current thread immediately after runonuithread call might schedule the runnable, but you can never be really sure.
Edit: Or you could create a Handler which shows Progress bar and wait for it to be shown and then continue
The reason You don't see the loading dialog is that you call a blocking function in your GUI thread/MAIN thread.When you set your dialog to visible you should let the GUI thread to keep running so it can draw the dialog on the screen.Moreover after 5 seconds that the GUI thread is blocked, the user will be presented with FORCE CLOSE/Wait pop up.
It is a bad practice to preform long operation of the gui thread, you MUST only can non blocking function in it.
Here is how you should do it:
//make sure mProgress is final
mProgress.setVisibility(View.VISIBLE);
new Thread(){
public void run(){
doLogin();
mProgress.setVisibility(View.INVISIBLE);
}
}.start();
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 want to make a Progress Dialog Box in my app to use when sending some information. But the code I wrote won't work. It the method send() executes but the dialog box never appears because it dismisses very quickly
Here is my code :
ProgressDialog myProgressDialog = ProgressDialog.show(Tents.this,
"Please wait...", "Sending...", true);
send();
myProgressDialog.dismiss();
goFour();
How do I make the Dialog Box Last a little longer?
First of all - you should not do send() in the same thread as show() and dismiss() - because you are effectively blocking UI thread during sending. The dialog will actually never show - because in order to show it after show() is called, you need to give the control back to the main looper in UI thread and simply finish handling whatever event you are handling. Otherwise the UI thread will never have a chance to draw your dialog.
The best idea is to start running send() in AsyncTask and call dismiss() in onPostExecute() (see http://developer.android.com/reference/android/os/AsyncTask.html to get idea how to run async task).
You are probably getting a progress dialog, but having it immediately dismiss as it has nothing to wait for.
I'll pretend you want this in OnCreate for my example:
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ProgressDialog pd = ProgressDialog.show(this, "Please wait...", "Sending...");
new Thread(new Runnable(){
public void run() {
send();
pd.dismiss();
}
}).start();
gofour();
}
EDIT: If it still goes away immediately, make sure send(); does something that actually takes some time. ;)
The UI thread is used to start send() , this will not work and progress dialog will not be shown .
Call send in another thread or AsynTask doBackground and on completion dismiss the dialog.
If your send action is completing so quickly that the dialog is not displaying properly, might I suggest instead using an indeterminate progress bar in the upper right corner of your activity via requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS) and then utilizing setProgressBarIndeterminateVisibility(true/false).
"I guess my real question would then be how do I make it so that it lasts a little longer?" My answer would be WHY???!!!
I think you would be better showing an alert dialog to confirm your send function has completed, it would be annoying for the user having to wait for no reason!
I am developing my first Androïd application and I'm facing a problem when I want to display a ProgressDialog to indicate that a process is being run.
In my application, the user triggers a time consuming task by pressing a Button. The "OnClick" function of my "OnClickListener" is called when the user presses the Button. In this function, here is what I'm currently doing :
- creation and configuration of an instance of the ProgressDialog class,
- creation of a thread dedicated to the time consuming task,
- attempt to display the ProgressDialog using the "show" method,
- start of the thread,
- main Activity suspended (call of the "wait" function)
- wake up of the main Activity by the thread when it is finished
- removal of the ProgressDialog by calling the "dismiss" function.
Everything works fine (the result of the long task is correct) but the ProgressDialog nevers appears. What am I doing wrong?
Thanks in advance for the time you will spend trying to help me.
You should not call wait() to the Main Activity/UI thread, because this is actually freezing the UI including your ProgressDialog, so it has no time to fade in and will never be shown.
Try to use multithreading correctly: http://developer.android.com/resources/articles/painless-threading.html
final Handler transThreadHandler = new Handler();
public void onClick(View v) {
// show ProgressDialog...
new Thread(){
public void run(){
// your second thread
doLargeStuffHere();
transThreadHandler.post(new Runnable(){public void run(){
// back in UI thread
// close ProgressDialog...
}});
}
}.start();
}
I would suggest using AsyncTask, as it's purpose is exactly to handle this kind of problem. See here for instructions how to use it. Note that the linked page in Floern's answer also recommends the use of AsyncTask.
You would need to do the following:
subclass AsyncTask
override it's onPreExecute() method to create and show a ProgressDialog. (You could hold a reference to it in a member of your subclass)
override it's doInBackground() method to execute your time consuming action.
override it's onPostExecute() method to hide your dialog.
in your activity, create an instance of your subclass and call execute() on it.
If you make your subclass an inner class of your activity, you can even use all of your activity's members.