Android : can't stop handler when runs progress bar dialog - android

I make a dialog based on this website http://www.mkyong.com/android/android-progress-bar-example/
When progress bar goes to 100%, dialog closed but a toast still appears continuously. I noticed that after bar goes to 100%, progressHandler still runs looping.
How can I solved this problem?
Thing that I want : When progress bar goes to 100% then dialog closed and Toast shows and closed.
Thread background = new Thread(new Runnable() {
#SuppressWarnings("null")
public void run() {
try {
while (dialog.getProgress() <= dialog.getMax()) {
// wait 500ms between each update
Thread.sleep(100);
// active the update handler
progressHandler.sendMessage(progressHandler.obtainMessage());
}
} catch (java.lang.InterruptedException e) {
// if something fails do something smart
Toast.makeText(getApplicationContext(), "Error Occurs",Toast.LENGTH_LONG).show();
}
}
});
// start the background thread
background.start();
}
// handler for the background updating
Handler progressHandler = new Handler() {
public void handleMessage(Message msg) {
dialog.incrementProgressBy(increment);
if(dialog.getProgress()==100){
editor.putInt("lastestSummaryNoSent",summary.getCurrentSummaryNo());
editor.commit();
dialog.dismiss();
Toast.makeText(getApplicationContext(), "Update Finished", Toast.LENGTH_LONG).show();
}
}
};

This error
Can't create handler inside thread that has not called Looper.prepare()
is because of the Toast you have provided inside the background Thread. Remove the Toast inside the Catch phrase and you will be good to go.

Related

Android: Multiple handlers in one Activity

I have a single handler instance, and I try to post two Runnables. But what I observe is only the latest Toast is getting printed on the device.
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(),"Showing from main activity",
Toast.LENGTH_SHORT).show();
}
});
handler.post(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Toast.makeText(getApplicationContext(),"Showing from main activity new",
Toast.LENGTH_SHORT).show();
}
});
As per the explanation of Handler, it enqueues the runnables into the messages queue of the thread to which it it associated. Which means Both the toast should be displays in the order in which they are enqueued.
Can someone please explain this?
When you make a Handler associated with the main looper, you should keep in mind that it's associated with the main thread. So calling Thread.sleep in the main thread is absolutely discouraged and should be avoided.
Toasts use the UI thread as well, but you prevent it from appearing by freezing this thread. The steps happening in your code are as follow:
The action to show first Toast is enqueued
The action to show second Toast is enqueued
// First action execution
Make the thread sleep for 3
seconds
Showing first toast is enqueued
// Here first Toast should appear, but it doesn't happen right at the moment you called the method. Treat it as another message enqueued in the main looper
Make the thread sleep for 3 seconds
Showing second toast is enqueued
First toast is shown
Second toast is shown
In the end both toasts are shown, but you can see only the last one, because it's shown after the first and covers it. If you want to show two toasts with a short delay, use post delayed method, or something like:
final Handler handler = new Handler(Looper.getMainLooper());
final Context context = getApplicationContext();
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(context, "Showing from main activity",
Toast.LENGTH_SHORT).show();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Toast.makeText(context, "Showing from main activity new",
Toast.LENGTH_SHORT).show();
}
}, 3000);
}
});

How to stop background thread, `interupt` not working

Consider this example:
Thread thread = new Thread(new Runnable() {
public void run() {
// Sleep for 5000ms
// Show toast message
}
});
Now I will start this thread on button click in MainActivity and right after that I would exit the activity on back button press, but in overided method onBackPressed following code is implemented:
If(thread != null)
thread.interupt();
finish();
After few seconds toast message is shown, why is that?
interrupt, clears the interrupt status of your thread and will cause the InterruptedException to be thrown. So if your thread is sleepin, and while it is asleep, you call interrupt, it will be woken up, and the execution flow will continue from the instruction that follows the catch block. Assuming you have something really simple like:
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackThreace();
}
runOnUiThread(TOAST);
}
or
public void run() {
while(true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackThreace();
}
runOnUiThread(TOAST);
}
}
both will shown the Toast even though you called interrupt()
While blackbelt has already explained the reason why this happens, here is how you can get around the problem.
The best way to interupt a thread is to use a if-boolean-break method.
So if i were to re-write you code it would be along the following lines
onBackPressed:
isBackPressed = true;
inside the thread's run method:
Thread thread = new Thread(new Runnable() {
public void run() {
// Sleep for 5000ms
if(!isBackPressed){
// Show toast message
}
}
});

ProgressDialog appears too late and disappears too fast

I try to show a progress dialog upon showing a sliding drawer.
this is opening drawer event handler:
public void onDrawerOpened(View drawerView) {
progress = ProgressDialog.show(activity, "dialog title",
"dialog message", true);
openDrawer();
}
Inside openDrawer() i call a function fillCommunityList() that i need to show the progress dialog while its execution
fillCommunityList() implementation is as the following:
private void fillCommunityList(){
new Thread(new Runnable() {
#Override
public void run() {
try {
// Here you should write your time consuming task...
UIManager manager = new UIManager(activity);
coms = manager.getCommunities();
progress.dismiss();
getOutTread = false;
} catch (Exception e) {
}
getOutTread = false;
}
}).start();
// to stop code till thread be finished
while(getOutTread){ }
SlidingMenuExpandableListAdapter adapter = new SlidingMenuExpandableListAdapter(this,
navDrawerItems, coms, mDrawerList);
mDrawerList.setAdapter(adapter);
}
Note:
I put a thread just to make progress dialog works
My problem is the following two points:
1- progress dialog appears too late for sudden and then disappears
2- Thread takes alot of time in its execution (without thread fillCommunityList() takes around 10 seconds but with a thread it takes more than a minute)
Note: manager.getCommunities() has asyncTask in its implementation
The problem is the following line
while(getOutTread){ }
this is call busy waiting. The UI Thread is busy looping and can't, at the same time, draw/update the ProgressDialog

Change TextView text on value change

I'm trying to do something like this after clicking a button:
case R.id.bcheckConnection:
if (IPok()) {
PlcState.ErrPlc = false;
Constant.adressIpPlc = adresIp.getText().toString();
final ProgressDialog dialog = ProgressDialog.show(Main.this, "", "Trying to connect...");
new Thread(new Runnable() {
public void run() {
timeout = network.testConnection(Constant.adressIpPlc, 102, 20000);
dialog.dismiss();
}
}).start();
if (timeout > -1) {
PlcState.ErrPlc = false;
stanPolaczenia.setText("Connection established. Timeout = ");
stanTimeout.setText(Long.toString(timeout));
currentIp.setText(Constant.adressIpPlc);
} else {
PlcState.ErrPlc = true;
stanPolaczenia.setText("Error");
stanTimeout.setText("");
currentIp.setText(Constant.adressIpPlc);
}
} else {
Toast.makeText(Main.this, "Wrong IP", Toast.LENGTH_LONG).show();
}
break;
So is it possible to change text AFTER thread stops running?
You can use Thread.join() to block the current thread until the given thread is finished:
Thread myThread = new Thread(new Runnable() {
public void run() {
// Do something
}
});
myThread.start();
// Do some things
// and block current thread until myThread is finished
myThread.join();
// Continue execution after myThread got finished
Edit: As #Eric already mentions in the question comments: for your (example) situation it seems to make more sense to use AsyncTask. It has two events (that are called on the UI thread), so you can update your UI with progress updates and when the task finished. For an AsyncTask example see: AsyncTask Android example

android - progress bar is not dismissed properly

In OnResume(), I make web service call in thread here i used progress bar for indicating the process it works fine but suppose i uses the app after sometime i put the device idle after that open the app once again this time progress bar is not dismissed.It's not regularly happens sometimes it happens. Why?
How can i make it to away from this? If you need more info plz let me know.
Code :
Edit:
public void onResume()
{
super.onResume();
pdMessages = ProgressDialog.show(getParent(), "", "Please wait...", true);
Thread thImportbtn = new Thread()
{
public void run()
{
try
{
//Get internal messages
strInternalInboxWSR = GetInternalInboxMessages();
} catch (SoapFault e) {
e.printStackTrace();
}
dh_Messages_Handler.post(checked_internalinbox_response);
handler.sendMessage(handler.obtainMessage());
}
};
thImportbtn.start();
}
private Handler handler = new Handler()
{
#Override
public void handleMessage ( Message message )
{
pdMessages.dismiss();
}
};
You can use Handler Class to dismiss your ProgressDialog, like below
private Handler handler = new Handler()
{
#Override
public void handleMessage ( Message message )
{
progressDialog.dismiss();
}
};
you can use following statement to call Handler class,
handler.sendMessage(handler.obtainMessage());
You are Trying To Dismiss ProgressDialog in Non-UI Thread, So can't Dismiss proper.
you should put your dismiss code( pdMessages.dismiss();) in Handler Using Overriding handleMessage method
Use AsyncTask is better.

Categories

Resources