I want to show this dialog, while the thread tries to build up a connection, but the dialog will not show up when I press the button which starts this method.
public void add_mpd(View view) {
dialog = ProgressDialog.show(MainActivity.this, "", "Trying to connect...");
new Thread(new Runnable() {
public void run() {
try {
String child;
EditText new_mpd = (EditText) findViewById(R.id.new_mpd);
child = new_mpd.getText().toString();
mpd = new MPD(child);
children.get(1).add(child);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (MPDConnectionException e) {
e.printStackTrace();
}
}
}
).start();
adapter.notifyDataSetChanged();
dialog.dismiss();
}
It will not show up because the (blocking) work is done in another thread. That means, the start()-method of the Thread-class will not block.
Ergo, you show the Dialog, the Thread is started and the dialog is immediately dismissed (and therefore closed).
Put the call to dismiss() at the end of your run()-method and it should work just fine.
The above might be working for you, but you should not use the Thread-class directly. There are wrappers around it which are way more comfortable to use.
In Android, if you want to do long-term work off the UI-Thread, you should use an AsyncTask.
Additionaly, to build up on what Lukas said, you can look at this example.
http://www.helloandroid.com/tutorials/using-threads-and-progressdialog
public class ProgressDialogExample extends Activity implements Runnable {
private String pi_string;
private TextView tv;
private ProgressDialog pd;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
tv = (TextView) this.findViewById(R.id.main);
tv.setText("Press any key to start calculation");
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
pd = ProgressDialog.show(this, "Working..", "Calculating Pi", true,
false);
Thread thread = new Thread(this);
thread.start();
return super.onKeyDown(keyCode, event);
}
public void run() {
pi_string = Pi.computePi(800).toString();
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
pd.dismiss();
tv.setText(pi_string);
}
};
}
Related
I am building a project in which i use async task to show progress bar.
I am using get() method to wait the main thread so we can do the other task before .
but progress bar is showing after completion of doInBackground thered.
I Want to show the loading bar when the loading starts.
It will dismiss when onPostExecute calls.
public class TempConverterActivity extends Activity {
pojo p;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button b= (Button) findViewById(R.id.btn);
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
showResult();
}
});
}
private void showResult() {
try {
new LoadData().execute().get();
} catch (Exception e) {
Log.e("async brix--", e.getMessage());
}
runned();
}
private void runned() {
ArrayList<String> al = p.getData();
for (String str : al){
Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();
}
}
private class LoadData extends AsyncTask<Void, Void, Void> {
private final ProgressDialog dialog = new ProgressDialog(TempConverterActivity.this);
protected void onPreExecute() {
dialog.setMessage("Loading data...");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
protected void onPostExecute(final Void unused) {
if (dialog.isShowing()) {
dialog.dismiss();
}
}
#Override
protected Void doInBackground(Void... params) {
p = new pojo();
new SoapParser(p);
return null;
}
}}
Please help . Thanks in advance.
You can try following code,
progDailog = ProgressDialog.show(loginAct,"Process ", "please wait....",true,true);
new Thread ( new Runnable()
{
public void run()
{
// your code goes here
}
}).start();
Handler progressHandler = new Handler()
{
public void handleMessage(Message msg1)
{
progDailog.dismiss();
}
}
Edited: In my previous answer I suggested using a Handler; however, AsyncTask eliminates the need to do this which I didn't spot.
Why do you feel the need to call AsyncTask.get()? This is a blocking call, and you call this from the UI thread, thus it is ultimately a race condition as to whether it or onPreExecute() is run first.
I see no reason why you should call get() in this context. You want to call runned() after the AsyncTask completes, but you could do this by launching a new thread from onPostExecute(). Alternatively you could do as you do now, using get(), but call that from a new thread instead of the UI thread.
here is my code,
public ProgressDialog loadingdialog;
public void ShowManager() {
//do something
}
public void startScan() {
loadingdialog = ProgressDialog.show(WifiManagementActivity.this,
"","Scanning Please Wait",true);
new Thread() {
public void run() {
try {
sleep(4000);
ShowManager();
} catch(Exception e) {
Log.e("threadmessage",e.getMessage());
}
loadingdialog.dismiss();
}
}.start();
}
startScan();
A basic progressdialog show function, but on the line where ShowManager() is called, getting error ,
01-07 23:11:36.081: ERROR/threadmessage(576): Only the original thread
that created a view hierarchy can touch its views.
EDIT:
ShowManager() is a function that change the view elements. shortly something like,
public void ShowManager()
{
TextView mainText = (TextView) findViewById(R.id.wifiText);
mainText.setText("editted");
}
I found the answer. I don't like to answer my own question but maybe this will help someone else. We cannot update most UI objects while in a separate thread. We must create a handler and update the view inside it.
public ProgressDialog loadingdialog;
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
loadingdialog.dismiss();
ShowManager();
}
};
public void ShowManager()
{
TextView mainText = (TextView) findViewById(R.id.wifiText);
mainText.setText("editted");
}
public void startScan() {
loadingdialog = ProgressDialog.show(WifiManagementActivity.this,
"","Scanning Please Wait",true);
new Thread() {
public void run() {
try {
sleep(4000);
handler.sendEmptyMessage(0);
} catch(Exception e) {
Log.e("threadmessage",e.getMessage());
}
}
}.start();
}
startScan();
use this instead of just loadingdialog.dismiss()
runOnUiThread(new Runnable() {
#Override
public void run() {
loadingdialog.dismiss();
}
});
This is because you are trying to dismiss the dialog from the thread, while it was created in the main UI thread. Try moving the ProgressDialog.show statement inside the Thread. I would prefer using AsyncTask as they are much simpler to manage as in this example
something like this it's 'ok':
public void startScan() {
new Thread() {
public void run() {
loadingdialog = ProgressDialog.show(WifiManagementActivity.this,
"","Scanning Please Wait",true);
try {
sleep(4000);
ShowManager();
} catch(Exception e) {
Log.e("threadmessage",e.getMessage());
}
loadingdialog.dismiss();
}
}.start();
}
note the position of ProgressDialog.show(...), here the dialog.dismiss() is called in the thread that created the dialog.
but the cleanest way to achive that it's by using AsynTask
final ProgressDialog Pdialog = ProgressDialog.show(SpinnerClass.this, "",
"Loading. Please wait...", true);
Thread ProgressThread = new Thread() {
#Override
public void run() {
try {
sleep(3000);
Pdialog.dismiss();
} catch(InterruptedException e) {
// do nothing
} finally {
}
}
};
ProgressThread.start();
TabHost1 TabHost1Object2 = new TabHost1();
TabHost1Object2.tabHost.setCurrentTab(2);
The problem I have with this thread is that it sets the current tab before the progress dialog starts. What have i done wrong ?
I want the dialog to run and dismiss, and after thread is done set tab.
use AsyncTask for this
some hints:
public class BackgroundAsyncTask extends AsyncTask<Void, Integer, Void> {
int myProgress;
#Override
protected void onPostExecute(Void result) {
TabHost1 tab = new TabHost1();
tab.tabHost.setCurrentTab(2);
progressBar.dismiss();
}
#Override
protected Void doInBackground(Void... params) {
while(myProgress<100){
myProgress++;
publishProgress(myProgress);
SystemClock.sleep(100);
}
return null;
}
#Override
protected void onProgressUpdate(Integer p) {
progressBar.setProgress(p);
}
}
The thing is that,you are starting a thread which will not affect your main UI. So what eventually happens is that, your thread will run separately which will now allow the next lines of your code to be executed. So in your case,
TabHost1 TabHost1Object2 = new TabHost1();
TabHost1Object2.tabHost.setCurrentTab(2);
these lines will be executed irrespective to your thread which is also getting executed simultaneously. So what you can do here is you can either go for AsyncTask or create handlers to handle this part of your code. You have to change your code like this.
Do this in your onCreate()
Handler handler;
handler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.what == 0) {
Pdialog.dismiss();
TabHost1 TabHost1Object2 = new TabHost1();
TabHost1Object2.tabHost.setCurrentTab(2);
}
};
And now in your thread,call the handler like this,
final ProgressDialog Pdialog = ProgressDialog.show(SpinnerClass.this, "",
"Loading. Please wait...", true);
Thread ProgressThread = new Thread() {
#Override
public void run() {
try {
sleep(3000);
} catch(InterruptedException e) {
// do nothing
} finally {
handler.sendEmptyMessage(0);
}
}
};
this will allow your tabhost to wait until the thread gets executed and will come into view after thread finishes execution.
I'm having some problems displaying a ProgressDialog. I have a method that scrapes information from a website, and I want to show the user some kind of "Loading" window instead of the app just looking like it is hanging for a second or two when it is working.
Everything works fine when I don't implement a ProgressDialog & Thread, but as soon as I try to implement a Thread to do the heavy lifting, the AboutMe View window is empty.
I have a MainActivity with a TextView that registers a OnClickListener.
A Click on the TextView does a:
startActivity(new Intent(getBaseContext(), AboutMe.class));
This is most of the AboutMe.class Activity:
public class AboutMe extends Activity {
private ProgressDialog aboutMeProgressDialog;
private String htmlAboutMe = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
getAboutMe(); // Get information from Internet
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFeatureDrawableResource(Window.FEATURE_NO_TITLE, android.R.drawable.ic_dialog_alert);
setContentView(R.layout.abutme);
TextView tvAbout = (TextView) findViewById(R.id.aboutMe);
tvAbout.setText(Html.fromHtml(htmlAboutMe));
}
private void getAboutMe() {
try {
aboutMeProgressDialog = ProgressDialog.show(AboutMe.this, "", "Loading");
new Thread() {
#Override
public void run() {
try {
/** Code to scape webpage **/
}
catch (Exception exp) {
exp.printStackTrace();
}
handler.sendEmptyMessage(0);
}
}.start();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
private final Handler handler = new Handler() {
#Override
public void handleMessage(final Message msg) {
aboutMeProgressDialog.dismiss();
}
};
I'm clearly missing out on something trivial, but I've tried to Google just about everything I can think of, but still can't get a Thread together with ProgressDialog to work for me.
please use run on ui thread method
instead of handler.sendEmptyMessage(0); use this code and remove handle message
runOnUiThread(new Runnable() {
#Override
public void run() {
aboutMeProgressDialog.dismiss();
}
});
dude let me know if this was successful,it works most of times
please call getAboutMe() method after calling super.onCreate(savedInstanceState);
public class Connection extends Activity implements Runnable {
public static final int CONNECTION_ERROR = 1;
public static final int CONNECTION_DONE = 3;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
createConnection();
}
public void createConnection() {
m_ProgressDialog = ProgressDialog.show(this, "Please wait...","Connection ...", true, false);
thread = new Thread(this);
thread.start();
}
public void run() {
int i = connecTion();
handler.sendEmptyMessage(i);
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.what == CONNECTION_ERROR) {
m_ProgressDialog.dismiss();
AlertDialog.Builder alt_bld = new AlertDialog.Builder(thisA);
alt_bld.setMessage("Failed to connect to the server");
alt_bld.setCancelable(false);
alt_bld.setNegativeButton("Quit",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog, int id) {finish();}});
alt_bld.setPositiveButton("Try Again",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//HERE IS THE PROBLEM
/*m_ProgressDialog.show(thisA, "Please wait...", "Connection ...", true, false);
connecTion();*/
}
});
AlertDialog alert = alt_bld.create();
alert.setTitle("ChatApp");
alert.setIcon(R.drawable.icon);
alert.show();
}
else {
m_ProgressDialog.dismiss();
finish();
}
}
};
private int connecTion() {
/** Create a connection */
try {
//Function to create the connection (throwing error if there is a pb)
} catch (Exception e) {
Log.e("App","Failed to connect");
return CONNECTION_ERROR;
}
//If no error left, everything is OK
return CONNECTION_DONE;
}
I want to realize a "Try Again" button which launch again the thread to create the connection and the ProgressDialog in parallel.
How can I kill the "old" thread and create the new one properly?
Is it better to keep the same thread alive and just dealing with Handler and Messages? Use service?
Thank you !
You could setup a pipeline thread; I've detailed how you can do this on my blog (Threading 5). Also note that once a thread completes, it cannot be restarted again. You can however, keep a single thread alive and schedule work to it.
Another approach is to instantiate a single thread each time you offload the background task; it'll complete and expire - this is the simpler way of going about it. It might be worth looking into AsyncTask.
The way I usually handle this is through a helper Class that extends Thread so:
public class DoAyncStuff extends Thread
{
protected Handler mHandler;
public DoAyncStuff(Handler handler)
{
mHandler = handler;
}
public void run()
{
// Do async stuff here
// send message back once done
Message msg = Message.obtain(mHandler, CONNECTION_ERROR_OR_OTHER_MESSAGE);
mHandler.sendMessage(msg);
}
}
// to use
DoAyncStuff asyncTask = new DoAyncStuff(mContext, mHandler)
asyncTask.start();
// Then in your handler you can check to async task results and restart if needed
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (msg.what == CONNECTION_ERROR_OR_OTHER_MESSAGE) {
// prompt to try again
// if trying again
DoAyncStuff asyncTask = new DoAyncStuff(handler)
asyncTask.start();
}
}