Here is the problem
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
progressDialog = ProgressDialog.show(ContactMainActivity.this, "",
"Loading. Please wait...",true);
setContentView(R.layout.contactlist);
contactListView=getListView();
contactListView.setTextFilterEnabled(true);
contactListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
Thread t = new Thread() {
public void run() {
try{
runOnUiThread(new Runnable() {
public void run() {
//stuff that updates ui
queryAllRawContacts();
progressDialog.dismiss();
}
});
registerForContextMenu(contactListView);
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
// dismiss the progress dialog
}
};
t.start();
}
this is onCreate method of my activity class.
This activity actually one tab of a tabwidget. So when I click this tab and run the activity, it waits about 2 seconds and then show progress dialog like 10 millisec and updates the UI with the data. and dismiss progress dialog. What I would like to achieve is that as soon as the tab is clicked, the progress dialog will be shown and it takes about 2-3 seconds to load data. after loading and updating the UI the progress bar will be dismissed.
Thanks
queryAllRawContacts() needs to not be run on the UI thread. Change your code to the following:
Thread t = new Thread() {
public void run() {
queryAllRawContacts();
try{
runOnUiThread(new Runnable() {
public void run() {
//stuff that updates ui
progressDialog.dismiss();
}
});
registerForContextMenu(contactListView);
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
// dismiss the progress dialog
}
};
t.start();
Related
I want to implement ProgressBar in Android and when I execute the program, Progressbar should show for up to 2 seconds. I can't get it to work properly but I can't figure out why.
public void myThread(){
Thread th=new Thread(){
#Override
public void run(){
try
{
while(mRunning)
{
Thread.sleep(10L);//10s wait
YourCurrentActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
//DISMISS PROGRESS BAR HERE
mRunning=false;
}
});
}
}catch (InterruptedException e) {
// TODO: handle exception
}
}
};
th.start();
}
I have tried this but it does not giving me output as i want.
That what handlers are for in Android.
Example:
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
// cancel or dismiss your progressbar
}
}, 2000);
CASE: I have a button and list-view in the activity. On click of the button I have added a click listener, which starts a new thread in which I update the progress bar. After the job is done i.e. progress bar is done 100%, I want to update the list-view.
final OnClickListener mStartScan = new OnClickListener() {
#Override
public void onClick(View v) {
// prepare for a progress bar dialog
progressBar = new ProgressDialog(v.getContext());
progressBar.setCancelable(false);
progressBar.setMessage(getString(R.string.text_scanning_inbox));
progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressBar.setProgress(0);
progressBar.setMax(totalSms);
progressBar.show();
progressBarStatus = 0;
Thread progressThread = new Thread(new Runnable() {
public void run() {
while (progressBarStatus < totalSms) {
// process some tasks
progressBarStatus = someStuff();
// Update the progress bar
progressBarHandler.post(new Runnable() {
public void run() {
progressBar.setProgress(progressBarStatus);
}
});
}
if (progressBarStatus >= done) {
// sleep 1 seconds, so that you can see the 100%
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// close the progress bar dialog
progressBar.dismiss();
// this method updates the list
populateList();
}
}
});
progressThread.start();
// try {
// progressThread.join();
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// } finally {
// populateList();
// }
}
};
PROBLEM: When I update the listview after completion of the task and dismissing progress bar, I get an exception which says that the view can be updated only from the thread in which it is created.
android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
WHAT ELSE I TRIED: I tried waiting for the thread which is running progress bar to complete and then update listview from the main thread.
try {
progressThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
populateList();
}
However, this does not work. It does not show the progress bar at all.
I used this:
private ProgressDialog progressBar;
class MyTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar = new ProgressDialog(getApplicationContext());
progressBar.setMessage("please, waiting ...");
progressBar.setCancelable(false);
progressBar.show();
}
#Override
protected String doInBackground(String... params) {
try {
// get info and set them in my model ...
} catch (Exception e) {
e.printStackTrace();
}
return params[0];
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (null != progressBar && progressBar.isShowing()) {
progressBar.dismiss();
}
// do work in UI and set info adapter and refresh list ...
populateList();
myListView.invalidateViews();
}
}
for more information:
http://developer.android.com/reference/android/widget/ArrayAdapter.html#notifyDataSetChanged%28%29
Only the original thread that created a view hierarchy can touch its views.
Here original thread refers to the ui thread. You are attempting to update ui inside a thread which is not possible.
You cannot update ui from the back ground thread. You can use runOnUiThread .
runOnUiThread(new Runnable() //run on ui threa
{
public void run()
{
}
});
I would suggest you to use asynctask
You use use asynctask for this purpose. The onPreExecute(), onPostExecute() are invoked on the ui thread and you can use the same to update ui. You can do your background computation in doInbackground()
http://developer.android.com/reference/android/os/AsyncTask.html
Check the topic under heading The 4 steps.
class TheTask extends AsyncTask<Void,Void,Void>
{
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
// background computation and publish progress
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
// update progress bar
}
#Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
// cancel the progress bar
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
//display progress bar
}
}
Load asynctask on the ui thread
new TheTask().execute().
The error you are receiving is because of the fact that you are trying to change the UI components on a secondary thread. You should read this for more information on how to use threads on Android.
You can use the Activity method runOnUIThread() to call the populateList() method or whatever makes the updates on the UI(main) thread. If you read the doc mentioned above, you will find out more about this.
i got this progress dialog code:
new Thread() {
#Override
public void run() {
try {
sleep(1000);
}
catch (Exception e) {
Log.e("tag", e.getMessage());
}
// dismiss the progress dialog
progressDialog.dismiss();
}
}.start();
and i got text that will apear after some httprequest actions:
editText2.setText(stringEr);
how do i sync between them? i want that the text will be hidden untill the progress will finish
tnx!
You have to use Handlers to update your UI. A little modification here,
new Thread()
{
#Override
public void run()
{
try
{
//Instead of sleep, call your http request method here.
handler.sendEmptyMessage(0);
}
catch (Exception e)
{
Log.e("tag", e.getMessage());
}
// dismiss the progress dialog
progressDialog.dismiss();
}
}.start();
And create a handler in onCreate(),
Handler handler=new Handler()
{
public void handleMEssage(Message msg)
{
if(msg.what==0)
editText2.setText(stringEr);
}
};
i think you should use AsyncTask for that and you can hide in OnPreExecute Method i mean when asynctask in started and show in OnPostExecute method. after complete the progress.
Android skip the painful Threading concept, Use Asyntask class.
http://developer.android.com/reference/android/os/AsyncTask.html
private class UIOperation extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
//show dialog
}
#Override
protected String doInBackground(String... params) {
//collect data
return null;
}
#Override
protected void onPostExecute(String result) {
//dismiss dialog
//update UI
}
}
I updated my code like Andro wrote about to me:
public class ZiiziiActivity extends Activity {
ProgressDialog pd;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pd = new ProgressDialog(ZiiziiActivity.this);
final Handler handler = new Handler()
{
public void handleMessage(Message msg)
{
if(msg.what==0)
{
pd.dismiss();
}
}
};
Button end = (Button) findViewById(R.id.button2);
end.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Working...");
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.show();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
for (int i=0;i<1000000;i++)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} //To denote a delay in background processing
}
handler.sendEmptyMessage(0);
}
}); t.start();
}
});
}
}
But when the progress start, it never ends.
What can be wrong?
This is so simple. The basic fact behind this is as follows.
Your progress dialog runs in the main UI. Your for loop here gets executed so soon and takes more priority and hence you are not able to see your progress dialog but the fact is, your code works fine and progress dialog does show up for fraction of seconds which the human eye can't catch.
Usually people use a progress dialog when they do something in the background thread and not the main thread. So you will have to change a little bit of your code. They are,
1) Surround your for loop with a thread like this,
Button end = (Button) findViewById(R.id.button2);
end.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
ProgressDialog pd = new ProgressDialog(ZiiziiActivity.this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("Working...");
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.show();
Thread t = new Thread(new Runnable() {
#Override
public void run() {
for (int i=0;i<1000000;i++)
{
Thread.sleep(100); //To denote a delay in background processing
}
handler.sendEmptyMessage(0);
}
});
t.start();
}
});
2) Now add a handler to your onCreate() like this:
handler = new Handler()
{
public void handleMessage(Message msg)
{
if (msg.what == 0)
{
pd.dismiss();
}
};
Note that you can't update your UI from a background thread. So in order to update the UI from some other worker thread you go for handlers. So once your for loop gets completed, a call will be made to handlers which updates the UI. (In this case it cancels the progress dialog).
Your code is the same as you would do the following.
pd.show();
pd.dismiss();
The method show gets called, but immediately the dialog will be dismissed because your for loop is not time comsuming at all. In addition, you are blocking the UI. So if you replace your empty for loop through a time-consuming operation, your progress won't run because you block the UI thread.
My application fetches some html code from the internet and when done , displays it on the devices screen. Since it takes about 3-4 seconds to do that , in this time the screen stays black , I'd like to use a progress dialog. This is my code :
package com.nextlogic.golfnews;
// ALL THE IMPORTS ....
public class Activity1 extends Activity {
private ProgressDialog progressDialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
progressDialog = ProgressDialog.show(Activity1.this, "", "Loading...");
new Thread()
{
public void run()
{
try
{
sleep(2000);
// HERE I'VE PUT ALL THE FUNCTIONS THAT WORK FOR ME
}
catch (Exception e)
{
Log.e("tag",e.getMessage());
}
// dismiss the progressdialog
progressDialog.dismiss();
}
}.start();
The program works but it doesn't display anything anymore. I have one error in logcat :
Only the original thread that created a view hierarchy can touch its views.
Could you please help me ? Thanks in advance.
The error is explicative enough. To update one visual object you must run the changes inside main thread. A quick and dirty fix could be calling the update code inside runOnUiThread().
However in your case I would use an AsyncTask to download and update the progress of the progress bar. The task has the property to run on UI thread when it ends (so you can update the views there, such as dismissing the progress dialog)
Here is an example how to use an AsyncTask to display a download progress dialog.
Update
Stackoverflow already has the answers to all your question. Here is an example of an AsyncTask to download some content and display the download progress. Just what you want.
Update 2
Ok here is your code using an AsyncTask:
public class Activity1 extends Activity
{
private ProgressDialog progressDialog;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new AsyncTask<Integer, Integer, Boolean>()
{
ProgressDialog progressDialog;
#Override
protected void onPreExecute()
{
/*
* This is executed on UI thread before doInBackground(). It is
* the perfect place to show the progress dialog.
*/
progressDialog = ProgressDialog.show(Activity1.this, "",
"Loading...");
}
#Override
protected Boolean doInBackground(Integer... params)
{
if (params == null)
{
return false;
}
try
{
/*
* This is run on a background thread, so we can sleep here
* or do whatever we want without blocking UI thread. A more
* advanced use would download chunks of fixed size and call
* publishProgress();
*/
Thread.sleep(params[0]);
// HERE I'VE PUT ALL THE FUNCTIONS THAT WORK FOR ME
}
catch (Exception e)
{
Log.e("tag", e.getMessage());
/*
* The task failed
*/
return false;
}
/*
* The task succeeded
*/
return true;
}
#Override
protected void onPostExecute(Boolean result)
{
progressDialog.dismiss();
/*
* Update here your view objects with content from download. It
* is save to dismiss dialogs, update views, etc., since we are
* working on UI thread.
*/
AlertDialog.Builder b = new AlertDialog.Builder(Activity1.this);
b.setTitle(android.R.string.dialog_alert_title);
if (result)
{
b.setMessage("Download succeeded");
}
else
{
b.setMessage("Download failed");
}
b.setPositiveButton(getString(android.R.string.ok),
new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dlg, int arg1)
{
dlg.dismiss();
}
});
b.create().show();
}
}.execute(2000);
new Thread()
{
#Override
public void run()
{
// dismiss the progressdialog
progressDialog.dismiss();
}
}.start();
}
}
You need to do this way
runOnUiThread(new Runnable() {
public void run() {
// Do Your Stuff
}});
Dismiss your dialog like this:
Handler handler = new Handler();
handler.post(new Runnable(){
public void run(){
progressDialog.dismiss();
}
});
Create a UI thread after completing network operation
runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.dismiss();
}
});
The top answer works great, so here is an example to implement an AsyncTask in MonoDroid (thanks to Greg Shackels): http://mono-for-android.1047100.n5.nabble.com/AsyncTask-td4346647.html