I've found that a lot of people are having a similar problem but I am simply trying to show a dialog while I am grabbing some data off a URL and then dismiss properly after the data is retrieved. Here is what I'm trying to do (This is in my onClick() method for a refresh button):
dialog.show();
// do some work
dialog.dismiss();
Doing it this way you never really see the dialog at all. I've tried doing it using an extra thread such as:
Thread t = new Thread() {
public void run() {
dialog.show();
}
};
But this way I get an error and a force close down...
What is the best method to do this?
For the task you are trying to implement:
dialog.show();
// do some work
dialog.dismiss();
Now, to implement above, there is concept of AsyncTask, the best way to implement Threading task, as its also known as Painless Threading in Android.
AsyncTask has 4 main methods:
onPreExecute() - Here you can show ProgressDialog or ProgressBar.
doInBackground() - Here you can do/implement background task
onProgressUpdate() - Here you can update UI based on the intermediate result you receive from webservice call or from background task
onPostExecute() - Here you can dismiss dialog or make progress bar invisible. Also you can do the task which want to do after receiving result from background task or webservice call.
For this kind of task mostly I recommend you to use the AsyncTask. Here is one good example of it which will help you.
And for this question as You are making UI related task and for that please use the UI thread.
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
//Show or Hide your ProgressDialog
}
});
Try to use runOnUiThread of the Activity instead of using Thread.
Check the following code snippet.
runOnUiThread(new Runnable() {
public void run() {
dialog = new ProgressDialog(ctContext);
dialog.show();
}
}
});
I think this will help you.
Related
I've built an Android application which calls a TCP socket related thread from six different activities. It works just and fine, but as I try to add a simple dialog witch asks the user's id/pw just before starting the thread(the retrieved data will be required in the thread), I'm having trouble. There is an adapter class which is actually called to start the threads, but it is also not an "Activity" which can implement a dialog.
Is there any way to solve this in some smarter method? Adding six same codes to create the dialog, and implementing additional six same handlers for each dialog will solve this, but I don't think that's not the right thing to do.
I tried to make the dialog an Activity(with a dialog theme), but it can't return any datas since the class which starts this dialog like activity is not an Activity(thus, startActivityForResult is invalid).
How can I solve this? Reforming the whole source is impossible, since it's over more than 20,000 line. Please help!
Threads which are not the UI/main thread cannot control UI elements like a dialog box. But there is a way to make a part of your code run on the main thread, and there you then can do such things.
You want to post something to the main handler like this:
new Handler().post(new Runnable{
public void run(){
//Be sure to pass your Activity class, not the Thread
AlertDialog.Builder builder = new AlertDialog.Builder(MyActivity.this);
//... setup dialog and show
}
});
Well, I finally figured out this easy issue.
To call a Dialog.show() on a non-UI Thread, I needed a Handler object created with the Looper.getMainLooper(). Then, just as #peedee explained, implement the things to do(UI related works) on the run() block.
Receiving the datas retrieved by the dialog wasn't difficult either. Adding some getter methods on my Dialog class, and adding an OnDismissListener before showing the dialog was all I required. (the OnDismissListener will react when the dialog's dismiss() function is called.)
Here's the code I wrote. Hope it might give help.
Handler mHandler = new Handler(Looper.getMainLooper());
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
Log.e("TESTRUNNABLE", "RUNNABLE LOADED");
cDialog = new TestDialog(mContext);
cDialog.setTitle("GROUP USER LOGIN");
cDialog.setOnDismissListener(new OnDismissListener(){
#Override
public void onDismiss(DialogInterface dialog) {
// TODO Auto-generated method stub
nameStr = cDialog.getNameStr();
pwStr = cDialog.getPwStr();
Toast.makeText(mContext, nameStr + ", " + pwStr, 3000).show();
Log.e("DISMISSLISTENER", nameStr + ", " + pwStr);
}
});
cDialog.show();
}
}, 0);
I already have idea on how to use a Progress Dialog when background action is being performed. But my question is how do I show a progress Dialog when I am dynamically inflating a huge layout.
Since I can't inflate a view in another Thread, I am using the main UI thread. Due to this my progress dialog is not getting priority and it doesn't show up. My UI hangs for several seconds until it gets loaded fully. I tried several approcahes but none seems to work.
progress.show(context,"","inflating UI...");
setNewContent(R.layout.my_profile,R.id.my_profile_menu_button,R.id.my_profile_all_elements_layout);
populateProfileList(); //Dynamic nested layouts being inflated.
I am basically looking for dynamic layout changes based on user actions. So I dont have any other way other than creating dynamic views. Can anyone suggest me a helpful idea.
I had an similar problem with ui-thread. I wanted to add much views to my layout at runtime, I wanted to show a ProgressDialog to inform the user, that it could take a while. I had tried it with AsyncTask, but the only chance to do this, was to implement my ui-methods into the onPostExecute-Method of AsyncTask. But this just freezes the ProgressDialog, because ProgressDialog even works on ui-thread. I found a solution, maybe not the best, but it works. Before starting ui-action, I show a Toast. Then, I created a Thread with a handler and delayed the execution. After ui-action was done, I showed a new Toast. Delay the thread, gives the Toast enough time to get showed:
Toast.makeText(ActivityContext.this,
R.string.start_message,
Toast.LENGTH_SHORT).show();
final Handler uiHandler = new Handler();
final Thread uiThread = new Thread(new Runnable() {
#Override
public void run() {
uiHandler.postDelayed(new Runnable() {
#Override
public void run() {
yourUIAction();
Toast.makeText(
ActivityContext.this,
R.string.finish_message,
Toast.LENGTH_SHORT).show();
}
}, 100);
}
});
uiThread.start();
You need to use a handler to be able to talk to the UI thread
//in some thread
uiHandler.sendEmptyMessage(1);
...
Handler uiHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if(msg.what == 1) {
//do somestuff
}
}
};
Using Async Task is much better idea to me, when you have to do something in background, while progress dialog shows up on screen and then when background task completes, update UI... for reference please follow the link...
http://labs.makemachine.net/2010/05/android-asynctask-example/
hope this helps...:-)
I'm using a thread so that I can show a progress dialog while my app loads some data. If there is an error it will stop the progress dialog and show the popup saying "error". However I found out that alert dialogs cannot run inside a UI thread and that I need to use a Handler. Can someone with help with this issue? Here is my code. Thanks
verifyCode.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
final ProgressDialog progressDialog = ProgressDialog.show(
Activate.this, "", "Loading...");
new Thread(new Runnable() {
public void run() {
try {
new AlertDialog.Builder(Activate.this)
.setTitle(getResources().getString(R.string.InvalidKey))
.setMessage(getResources().getString(
R.string.PleaseEntervalidRegistration)).setNeutralButton(
"OK", null).show();
progressDialog.dismiss();
//more code
}).start();
}
You can't make changes to UI element on non-UI threads. onClick will run on the UI thread, but since you spawn a Thread inside onClick then non-UI elements cannot be manipulated from inside that Thread. Move your AlertDialog and ProgressDialog calls to just prior to spawning the new Thread.
Also, as #lightblade suggested, If you need to do some sort of action which requires heavy background processing and UI manipulation based on that processing, then you should use AsyncTasks. It provides methods you can override for pre-processing, actual processing, post-processing, and updating progress.
Tips or ideas on how ProgressDialog can communicate with asyncTask.
For example when I click the button, the program will validate the input to internet, This is should not be interupted. so I use ProgressDialog.
After progressDialog.dismiss(), I need to refresh the view by calling the asyncTask.
I have tried some ways but it's failed, for example
* I execute asynTask after progressdialog.dismiss().
* put execution asynctask inside dialogbox after progressdialog thread.
in other word, is there any way to tell asynctask that progressdialog has been dismissed. Or is there communication such as message between threads ?
here is the example of my code:
btnPost.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
stockProgressDialog = ProgressDialog.show(PostActivity.this,
"Please wait...", "Check the post");
new Thread() {
public void run() {
try{
/* Connect to Internet API */
stockProgressDialog.dismiss();
} catch (Exception e) { }
// Dismiss the Dialog
}
}.start();
new LookUpTask().execute();
}
});
Yes, there is a way to tell asyncTask that progressDialog has been dismissed. you can use one onDismissListener
#Override
public Dialog onCreateDialog(int id){
if(id==DIALOG_PROGRESS_DIALOG){
stockProgressDialog = new ProgressDialog(Main.this);
stockProgressDialog.setTitle("Please wait...");
stockProgressDialog.setMessage("Check the post");
stockProgressDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
textView.setText("Waiting the 5 secs...");
myAsyncTask.execute("start it");
//Or myAsyncTask.cancel(true); if you want to interrupt your asyncTask
}
});
return stockProgressDialog;
} else return super.onCreateDialog(id);
}
You can cancel an AsyncTask by calling AsyncTask.cancel(..) and then start up a new AsyncTask. You are not supposed to run the AsyncTask as a parallel activity - it is supposed to be able to run and finish without outside intervention.
Extend async and look into returning a result from doInBackground. onProgress update can dismiss your Progress dialog under control of the async task. Handle the result from doInBackground in onPostExecute.
//create the task
theBackground = new Background();
theBackground.execute("");
--------
private class Background extends AsyncTask<String, String, String>{
protected String doInBackground(String...str ) {
publishProgress("##0");
//do a bunch of stuff
publishProgress(#001);
return("true");
}
protected void onProgressUpdate(String... str ) {
//do stuff based on the progress string and eventually
myProgressDialog.dismiss();
}
protected void onPostExecute(String result) {
}
}
I'm not sure why you're using a thread in one case, but an AsyncTask in another when you could just use two AsyncTasks... Actually, unless I'm missing something, in your case the most straightforward way is to combine the two bits of work into one AsyncTask and simply create and destroy the dialog in the AsyncTask callbacks. In pseudo-code:
onPreExecute
show dialog
doInBackground
do internet stuff
onPostExecute
update views
close dialog
Is there a reason why you're trying to update the views in its own AsyncTask? If you're updating views, you probably need to do the work in the UI thread anyway...
Can I use progress bar in android, without the thread?
HERE IS CODE OF MY CURRENT WAY OF IMPLEMENTING PROGRESS DIALOG
// Adding Progress bar
String[][] data; //Global variable
//called on onCreate() or onItemSelected
final ProgressDialog myProgressDialog;
myProgressDialog = ProgressDialog.show(ListingPage.this,"Please Wait", "Loading Date", true);
new Thread() {
public void run() {
try{
setSelected();
sleep(5000);
} catch (Exception e) { }
myProgressDialog.dismiss();
}
}.start();
populateList(Split.splitToTwoDimArray(data)); // populates the list view
HOPE ABOVE HELPS, IF USING THREAD THE LIST IS NOT BEING POPULATED.
Sure, you can always set the progress manually via
progressBar.setProgress(int progress);
Above question/added code is a bit confusing cause you asked how to use the progress bar without a thread but now in your code you're using a thread. I thought that you initially wanted to avoid.
Anyway, maybe you should use an AsyncTask instead of the Thread, which allows you to modify anything in the main UI thread.
https://sites.google.com/site/androidhowto/how-to-1/create-a-custom-progress-bar-using-asynctask
http://developer.android.com/reference/android/os/AsyncTask.html