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
Related
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 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.
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 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.
I seem to have consistent problems with timing threads and dialog windows. I've tried using a thread, or onCreate/onPrepare, or an AsyncTask to do some downloading/processing in the background. More often than not, when the background processing completes and dismisses the dialog window, control seems to return to the root thread (Activity/UI thread?) before the dialog is gone or the onPostExecute-like process is done. This makes me think I'm doing it incorrectly. Here is a typical structure (pseudo-code):
public class X {
protected String result = null;
protected ProgressDialog progressDialog;
public void onCreate() {
...
new XTask().execute();
progressDialog.show();
// result is null here, should be "hi"?
// do things with result, like barf on a NPE...sigh
}
private class XTask extends AsyncTask {
protected doInBackground() {
// Get URL.
// Look at contents, takes a few seconds.
// Return the result (should get sent to onPostExecute).
}
protected onPostExecute(r) {
result = r;
progressDialog.dismiss();
}
}
}
I would think that, after doPostExecute sets result and dismisses the dialog, processing then continues in the onCreate method. However, result is often (not always) null at this point in onCreate. Is there a better way to do this? Is this just due to the general crappiness of the emulator?
Thanks.
Edit: To be more concrete, my task (in doInBackground) fetches a URL and does a little processing on the response. This process takes 1-3 seconds. Then, theoretically, onPostExecute sets X.result to what was fetched. I know the URL content is valid and the response is good (not null). The problem is that during those 1-3 seconds, control returns to onCreate, as if the progressDialog never lived at all (it doesn't get displayed in the emulator at all, but that's normal I guess).
I had thought that calling dialog.show() was a blocking method, i.e., the dialog appeared and that method wouldn't continue until it disappeared, but that doesn't seem to be the case. Either my progressDialog.dismiss() is getting called before it should, before setting X.result, or not getting called at all, or dismiss() is happening faster/before the assignment, or something else entirely is going wrong...
Changing the order of the execute and progressDialog doesn't help, nor does moving it into onPreExecute(). Strangely, onPostExecute doesn't get called until I return in onCreate. If I have a Thread.sleep loop after execute (I thought giving it time would help), it never finishes the task until that loop finishes and I return. e.g.:
new XTask().execute();
int z=0;
while (response == null && z < 50) {
Thread.sleep(500);
z++;
}
if (response == null) return;
The task's onPostExecute method doesn't get called until "return". Hmmm...maybe being in onCreate is affecting it.
A ProgressDialog is usually used to block user interaction during loading or heavy processing but the main UI thread will continue to execute.
If you wish to perform some operation on the result you must do it in either onPostExecute of XTask or after you have gotten the result in doInBackground.
private class XTask extends AsyncTask {
#Override
protected void onProgressUpdate(/*params*/){
//modify UI
}
protected doInBackground() {
// Get URL.
// Look at contents, takes a few seconds.
//Option A: Now have the result, do some other processing here
//Cant modify UI components from here, If you need to modify a UI component from
//here call publishProgress() and modify the component in onProgressUpdate()
// Return the result (should get sent to onPostExecute).
}
protected onPostExecute(r) {
result = r;
//Option B do some processing on the result
//You can modify UI components from here
progressDialog.dismiss();
}
}
I would show the progress dialog before triggering the AsyncTask. Normally, when an AsyncTask gets executed, it takes a while to finish itself and in that time, the rest of the task calling method has already run. But in your case the task returns instantly which is probably why the dialog shows up AFTER the postexecute gets called under the AsyncTask.
I would think that, after doPostExecute sets result and dismisses the dialog, processing then continues in the onCreate method.
This is not true, when you call new XTask().execute() in UI thread, application create a worker thread and start running whatever you defied in AsyncTask.doInBackground() on this work thread, at this point (after calling new XTask().execute()), UI thread continue execute code after new XTask().execute().
The point you are talking about where your work thread finish and return to UI thread is AysncTask.onPostExecute(), this method is guaranteed to be called on UI thread after AsyncTask finish. this is the reason why it is called AsyncTask. Both of UI thread and work thread are running asynchronously.
If you want to make your UI thread blocked and wait for AsyncTask finish after XTask().execute(), you can to this:
XTask xTask = new XTask();
xTask.execute();
progressDialog.show();
xTask.get() // <-- this will make your UI thread blocked and wait for AsycnTask at this point
// result is null here, should be "hi"?
This is possible but not a good practice, as AsyncTask.get() will block execution on calling thread so probably get ANR exception.
To sum up
1. AysncTask.onPostExecute() is where process return from worker thread to UI thread, we don't care where and when it will be called on UI thread, we just need ensure it will be called on UI thread properly at some point in the future.
2. AsyncTask.get() by calling this method actually make you AsyncTask running synchronously with the calling thread.
Putting code into the task's onPostExecute should work, a simple test suggests it will (for me). However, I ended up writing a different solution which also works. I put most of the code into a Handler on the activity, which separates it from the UI thread entirely. My onCreate simply shows the loading ProgressDialog window and that's it--it just sits there, "loading". The background task does its thing and when finished, sends a message to the handler. This message tells the handler to dismiss the loading dialog and populate the list. If there are errors, different messages are sent and the handler shows an error dialog.