I want to show the waiting dialog but it doesn't show at all, which is weird because the thing that takes a lot of time is the setData() function where i get a json feed and I save them in database (it takes 3/5 seconds).
Here is my code :
ProgressDialog dialog = ProgressDialog.show(TabLayoutActivity.this, "", "Loading. Please wait...", true);
//refresh the view
taskLiteApplication.setData();
//change view
Intent myIntent = new Intent(TabLayoutActivity.this, TabLayoutActivity.class);
TabLayoutActivity.this.startActivity(myIntent);
//kill the dialog waiting
dialog.cancel();
I bet the issue is the fact that you are doing the all of this work on the UI thread, so the moment you start the dialog, the thread that starts and shows the window is actually freezing while you do the setData() work. You really should move the setData function to a background thread or a AsyncTask so that the UI thread can continue while you do the heavy work in the background.
private ProgressDialog dialog;
void doStuff()
{
dialog = ProgressDialog.show(TabLayoutActivity.this, "", "Loading. Please wait...", true);
HeavyTask task = new HeavyTask();
task.execute();
}
private class HeavyTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... args) {
//refresh the view
taskLiteApplication.setData();
return;
}
protected void onPostExecute(Void results) {
//change view
Intent myIntent = new Intent(TabLayoutActivity.this, TabLayoutActivity.class);
TabLayoutActivity.this.startActivity(myIntent);
//kill the dialog waiting
dialog.dismiss();
dialog = null;
}
}
I'm guessing taskLiteApplication.setData(); is operating in the UI thread instead of a background thread or it's operating in a background thread and the cancel is being called because it's cancelling in the UI thread.
Basic thread to fix your issue:
private ProgressDialog dialog; // Keep this global
private Handler mHandler;
void doStuff() {
dialog = ProgressDialog.show(TabLayoutActivity.this, "", "Loading. Please wait...", true);
mHandler = new Handler()
{
#Override public void handleMessage(Message msg) {
if (msg.obj != null) {
dialog.dismiss();
//change view
Intent myIntent = new Intent(TabLayoutActivity.this, TabLayoutActivity.class);
TabLayoutActivity.this.startActivity(myIntent);
}
}
};
//refresh the view
Thread t = new Thread(new Runnable() {
#Override public void run() {
// Assuming setData does NOT run on it's own background thread
taskLiteApplication.setData();
Message message = Message.obtain();
message.obj = "DONERAEREAR";
mHandler.sendMessage(message);
}
})};
t.start();
}
EDIT Added a handler, as pointed out by Wizetux the dialog needs to be cancelled in the UI thread
The benefit of this is you can send the handler error messages, warning messages, sucess messages and handle accordingly.
E.G.
message.obj = "ERROR";
mHandler.sendMessage(message);
then in the handler
if ((String)msg.obj.equals("ERROR")) { /* Handle Error */ }
Related
I have a procedure that extracts data from a database and populates it to the list. I want to display progress dialog box while query is executed, but it visually appears only after the query is executed. I believe I have to run a ProgressDialog in a separate thread, but followed few suggestions and could not make it work.
So in my Activity I just have
private void DisplayAllproductListView(String SqlStatement) {
ProgressDialog dialog =
ProgressDialog.show(MyActivity.context, "Loading", "Please wait...", true);
//..................
//..................
//execute sql query here
dialog.dismiss();
}
thanks
1.show your process dialog in main thread
2.start a new thread (such as Thread A) to process your heavy job
3.when done, use handler to send a message from Thread A to main thread, the latter dismisses the process dialog
code like this
private ProcessDialog pd;
private void startDialog()
{
pd = ProgressDialog.show(MainActivity.this, "title", "loading");
//start a new thread to process job
new Thread(new Runnable() {
#Override
public void run() {
//heavy job here
//send message to main thread
handler.sendEmptyMessage(0);
}
}).start();
}
Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
pd.dismiss();
}
};
Try something like this:
private class MyAwesomeAsyncTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog mProgress;
#Override
protected void onPreExecute() {
//Create progress dialog here and show it
}
#Override
protected Void doInBackground(Void... params) {
// Execute query here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//update your listView adapter here
//Dismiss your dialog
}
}
To call it:
new MyAwesomeAsyncTask().execute();
All you need to do, is to tell Android to run it on the main UI thread. No need to create a Handler.
runOnUiThread(new Runnable() {
public void run() {
progressDialog.dismiss();
}
});
I use AsyncTask in combination with a ProgressDialog.
See my code, I have a problem in onPostExecute.
If the task is running for the first time it get a Null Poiter Exception for progressDialog in handleMessage but calling dismiss() direct would work.
When I turn the phone before onPostExecute is reached, progressDialog.dismiss() does not work. why does the handler not always work?
public class UpdateTask extends AsyncTask<Void, Void, Void> {
private ProgressDialog progressDialog;
private Handler handler;
public UpdateTask(Act activity) {
progressDialog = ProgressDialog.show(Activity.this, "Wait",
"Wait");
progressDialog.dismiss();
handler = new Handler(){
#Override
public void handleMessage(Message msg) {
//run on UI Thread
switch( msg.what ){
case MSG:
progressDialog.show();
break;
case DETACH:
progressDialog.dismiss();
break;
}
}
};
}
void detach() {
activity=null;
//problematic
//progressDialog.dismiss();
//handler.sendEmptyMessage(DETACH);
}
#Override
protected Void doInBackground(Void... params) {
handler.sendEmptyMessage(MSG);;
return null;
}
protected void onPostExecute(Void result) {
if (activity==null) {
Log.w("RotationAsync", "onPostExecute() skipped -- no activity");
}
else {
//problematic
// progressDialog.dismiss();
handler.sendEmptyMessage(MSG);
progressDialog = null;
}
}
};
Any reason why you need the Handler inside the AsyncTask? If you want to control your progress dialogue from an AsyncTask using a Handler is the correct way, however, your current Handler would get created and destroyed each time you start a new UpdateTask. If you define your handler outside your AsyncTask, something like:
private Handler handler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
switch( msg.what ){
case MSG:
progressDialog.show();
break;
case DETACH:
progressDialog.dismiss();
break;
}
return false;
}
});
Now you can call handler.sendEmptyMessage(what) from any background thread safely, and the progressDialog will update on the UI thread only. Not a complete fix, and I don't know what int values you have defined for DETACH and MSG. But hopefully it will help. This is the method I use to update any UI element from a background task. Just do a bit more reading about the AsyncTask and updating UI elements.
See https://stackoverflow.com/a/4538370/719212
And you should read about onPreExecute() in Android documentation.
I am having problems getting the ProgressDialog wheel spinning. Here is my code:
final ProgressDialog dialog = ProgressDialog.show(this, "", "Loading...", true, false);
Thread thread=new Thread(new Runnable(){
public void run(){
runOnUiThread(new Runnable(){
#Override
public void run() {
if(dialog.isShowing())
// starts a foreground service, does database stuff,
// sets up a spinner with values
dialog.dismiss();
}
});
}
});
thread.start();
Everything goes as planned, I get the ProgressDialog, stuff happens in the background and once set, ProgressDialog goes away - the only problem is that the animation in ProgressDialog is not spinning, pretty much rendering it useless.
What am I doing wrong?
The code you omitted here
// starts a foreground service, does database stuff,
// sets up a spinner with values
must do something that block the UI thread. Just put them outside the runOnUiThread() Method.
Thread thread=new Thread(new Runnable(){
public void run(){
// starts a foreground service, does database stuff,
// sets up a spinner with values
runOnUiThread(new Runnable(){
#Override
public void run() {
if(dialog.isShowing())
dialog.dismiss();
}
});
}
});
ProgressDialog example using handler android
final ProgressDialog dialog = ProgressDialog.show(this, "Title",
"Message", true);
final Handler handler = new Handler() {
public void handleMessage(Message msg) {
dialog.dismiss();
}
};
Thread t = new Thread() {
public void run() {
// write process code here.
handler.sendEmptyMessage(0);
}
};
t.start();
Fix issue: ProgressDialog not working
Because you put the processing dialog in to wrong area, for example with my error:
I have a two activities: MainActivity and ShowingActivity, MainActivity will show processing dialog after new intent tranfer to ShowingActivity and ShowingActivity will get some DATA from server (it will be blocked here). When I call ProcessingDialog in MainActivity, it showed but not spinning because my Intent move to ShowingActivity and it block Ui because action of get DATA from server must wait some seconds. So I fixed it:
1/ in MainActivity call:
final Intent working = new Intent(getApplicationContext(),
WorkingActivity.class);
final ProgressDialog ringProgressDialog = ProgressDialog.show(
MainActivity.this, "Please wait ...", "Connecting ...",
true);
ringProgressDialog.setCancelable(false);
new Thread(new Runnable() {
#Override
public void run() {
//Menthod need time to load:
getDatafromServer();
if (BookListFragment.isLoaded) {
ringProgressDialog.dismiss();
startActivity(working);
return;
}
});
So it will not block Ui because MainActivity still runing after DATA was gotten.
And in ShowingActivity I will use this DATA (because I set DATA is a static String).
I have created a ProgressDialog in android and it works when I do a simple example.
For example, this works.
public void onClick(View v)
{
// Perform action on click
System.out.println("Progess Bar");
final ProgressDialog myProgressDialog = ProgressDialog.show(AndroidTestApplicationActivity.this,
"Please wait...", "Getting updates...", true);
new Thread()
{
public void run()
{
try
{
// Do some Fake-Work
sleep(5000);
}
catch (Exception e)
{
}
// Dismiss the Dialog
myProgressDialog.dismiss();
}
}.start();
}
But once I add in a reference to my custom class, it just stops running this new thread.
button1.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
// Perform action on click
System.out.println("Progess Bar");
// Display an indeterminate Progress-Dialog
final ProgressDialog myProgressDialog = ProgressDialog.show(AndroidTestApplicationActivity.this,
"Please wait...", "Getting Updates...", true);
new Thread()
{
public void run()
{
try
{
HealthySubObject hsObject = new HealthySubObject();
// Do some more work with my hsObject - nothing happens after this point.
sleep(5000);
}
catch (Exception e)
{
}
// Dismiss the Dialog
myProgressDialog.dismiss();
}
}.start();
}
});
What happens is that as soon as I click this button, the progress dialog flashes up on the screen real quick and then disappears. But if you look at my code, it should wait 5 seconds before disappearing. I have put debug statements before and after the reference to my custom class and I can see the statements before but not the ones after. Does anyone have any idea why that is happening? As long as my class is public I should be able to call it from a new thread, right?
I am still pretty new to android and this is my first adventure into multi-threaded android apps. Any help would be much appreciated.
SOLUTION
Thanks for your help everyone. It is working now.
button1.setOnClickListener(new View.OnClickListener()
{
public void onClick(View v)
{
// Perform action on click
System.out.println("Progess Bar");
//ProgressDialog dialog = ProgressDialog.show(AndroidTestApplicationActivity.this, "", "Loading. Please wait...", true);
// Display an indeterminate Progress-Dialog
final ProgressDialog myProgressDialog = ProgressDialog.show(AndroidTestApplicationActivity.this,
"Please wait...", "Doing Extreme Calculations...", true);
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
#Override
public void run()
{
HealthySubObject hsObject = new HealthySubObject();
ArrayList<HashMap<String, String>> onlineDB = hsObject.jsonToArray();
//
// more stuff goes here.
//
//
myProgressDialog.dismiss();
}
}, 1500);
}
});
I would really recommend to use Handler instead of Thread. Using the Thread.sleep method is actually discouraged. Something like this is much better:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
HealthySubObject hsObject = new HealthySubObject();
myProgressDialog.dismiss();
}
}, 5000);
The problem is that you need to be on the UI thread to do modify the UI, and inside the run() method of your Thread you are in a "background" thread. Try using a handler inside your thread when you need to access the UI thread.
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.