I have a HandlerThread, to which I keep posting a runnable every 5 seconds. Something like this:
HandlerThread thread = new HandlerThread("MyThread");
thread.start();
Handler handler = new Handler(thread.getLooper());
handler.post(new Runnable() {
public void run() {
//...
handler.postDelayed(this, 5000);
}
});
I need to quit the looper at some point, after 60 seconds or something like that.. so I write:
mainHandler = new Handler(Looper.myLooper()); //main thread's
mainHandler.postDelayed(new Runnable() {
#Override
public void run() {
thread.getLooper().quit();
}
}, 60000);
I think this causes the looper to quit abruptly, so I start getting this "warning" messages:
W/MessageQueue(3726): java.lang.RuntimeException: Handler
(android.os.Handler) {4823dbf8} sending message to a Handler on a dead
thread
I want to avoid this error msg, I thought that I could solve it by using the Looper.quitSafely() method.. but I checked the API and it's no longer available.
Does anyone know what happened to it? (It's not deprecated like some other methods).
Is there some way I can quit the looper safely? Thanks!
You could try to use a boolean to know if the code should be executed. Something like this:
private boolean runHandler = true;
...
HandlerThread thread = new HandlerThread("MyThread");
thread.start();
Handler handler = new Handler(thread.getLooper());
handler.post(new Runnable() {
public void run() {
if(runHandler){
//...
handler.postDelayed(this, 5000);
}
}
});
mainHandler = new Handler(Looper.myLooper()); //main thread's
mainHandler.postDelayed(new Runnable() {
#Override
public void run() {
runHandler = false;
}
}, 60000);
Im not Thread Guru, but this way can give you direction:
...
_thread.setRunning(true);
_thread.start();
..
public void stopThread(){
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
Log.e("test", "thread stopped");
} catch (InterruptedException e) {
Log.e("test", "can't stop thread, retrying...");
// we will try it again and again...
}
}
}
In your thread:
while (isRunning) {
//...
}
1st all you implement run method in loop (while(isRunnig){}).
On finish, you switch flag to false and "wait" for join.
Related
thread = new Thread() {
public void run() {
super.run();
System.out.println("run:" + Thread.currentThread().getName());
Looper.prepare();
handler = new Handler();
Looper.loop();
};
};
thread.start();
And then
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MActivity.this,Thread.currentThread().getName(),0).show();
}
});
the code run correct.
but the toast shows :"Thread-217"
that means the toast shows from a non-uithread.
why?
I am so sorry. I know answer. Toast is a special UI element. It can be showed from any thread. But the other UI elements ,such as Button TextView must only be touched in the UI-thread.
So,my code runs correct,but when you change the toast to Button ,is crashed.
You are trying to show toast in a UI thread using runnable thats why its going wrong
Thread background = new Thread(new Runnable() {
public void run() {
// Send message to handler
handler.sendMessage(msgObj);
}
};
private final Handler handler = new Handler() {
public void handleMessage(Message msg) {
//Catch the response and show the toast
String aResponse = msg.getData().getString("message");
Toast.makeText(getBaseContext(),"Not Got Response From Server.",
Toast.LENGTH_SHORT).show();
}
};
You must create the Handler in UiThread. The handler send the message to thread where it was created.
handler = new Handler();
thread = new Thread() {
public void run() {
super.run();
System.out.println("run:" + Thread.currentThread().getName());
Looper.prepare();
Looper.loop();
};
};
thread.start();
i have this Handler:
private Runnable mRunnableReset = new Runnable() {
public void run() {
Log.i("MyApp", "mRunnableReset");
}
};
private Handler mHandler = new Handler();
private Runnable mRunnable = new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(2000);
mHandler.post(mRunnableReset);
} catch (Exception e) {
// TODO: handle exception
}
}
}
};
I tried to use this code in my onDestroy() method
mHandler.removeCallbacks(mRunnableReset);
mHandler.removeCallbacksAndMessages(null);
but the mRunnable is still running (i can see the log in LogCat).
If I use mRunnable.destroy() my app crashes.
How can i stop this ?
Thank you.
Instead of using Thread.sleep() use postDelayed() while posting your Runnable (instead of regular post()).
Whoops you are using
while(true){
Thread.sleep(2000);
mHandler.post(mRunnableReset);
}
How will it stop then? It won't.
Instead it should be like,
private Runnable mRunnableReset = new Runnable() {
public void run() {
Log.i("MyApp", "mRunnableReset");
mHandler.removeCallbacks(mRunnableReset);
mHandler.post(mRunnableReset);
}
};
private Handler mHandler = new Handler();
private Runnable mRunnable = new Runnable() {
public void run() {
try {
Thread.sleep(2000);
mHandler.post(mRunnableReset);
} catch (Exception e) {
// TODO: handle exception
}
}
};
And then to stop your mRunnableReset use mHandler.removeCallbacks(mRunnableReset);
And better would be using mHandler.postDelayed(mRunnableReset, 2000) instead of Thread.sleep(2000);
Also check my answer here to get complete working of how Handler will work.
i want to start Asynchoronous task after some sleep time. For that i am using thread and i start my asynchronous task in that thread finally block. But it gives cant create a handler inside a thread exception.
i am using the following logic.
thread= new Thread()
{
public void run()
{
try
{
int waited = 0;
while (waited < 300)
{
sleep(100);
waited += 100;
}
}
catch (InterruptedException e)
{
// do nothing
}
finally
{
Load ld=new Load();
ld.execute();
}
}
};
thread.start();
Well, first of all, if the final goal is to run AsyncTask after some delay, I would use Handler.postDelayed instead of creating separate Thread and sleeping there:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
new Load().execute();
}
}, 300); //300ms timeout
But, if you really wanna make fun of Android, you can create HandlerThread - special thread which has looper in it, so your AsyncTask will not be complaining anymore:
thread= new HandlerThread("my_thread")
{
public void run()
{
try
{
int waited = 0;
while (waited < 300)
{
sleep(100);
waited += 100;
}
}
catch (InterruptedException e)
{
// do nothing
}
finally
{
Load ld=new Load();
ld.execute();
}
}
};
thread.start();
Please note that you are responsible for calling quit() on this thread. Also I'm not sure what happens if you quit this thread before AsyncTask is done. I don't remember where AsyncTask posts its results - to the main thread, or to the thread it was called from...
In any case, second option is just a mess, so don't do it:) Use the first one
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// Do whatever you want.
}
}, SPLASH_TIME_OUT);
}
You can use like above. there SPLASH_TIME_OUT is the millisecond value that u want to make a delay.
Use Handler class, and define Runnable YourAsyncTask that will contain code executed after sleepTime
mHandler.postDelayed(YourAsyncTask, sleepTime);
You must run AsyncTask in UI thread, so you can use something like this:
class YourThread extends Thread{
private Activity _activity;
public YourThread(Activity _activity){
this activity = _activity;}
public void run()
{
try
{
int waited = 0;
while (waited < 300)
{
sleep(100);
waited += 100;
}
}
catch (InterruptedException e)
{
// do nothing
}
finally
{
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
Load ld=new Load();
ld.execute();
}
});
}
}
}
and in your activity call thread like this:
YourThread thread = new YourThread(this);
thread.start();
also note: use soft reference to activity or do not forget kill thred when activity will be destroyed.
just do your like below code:
define a thread globally.
public static Thread thread;
thread= new Thread() {
public void run() {
sleep(time);
Message msg = setTextHandler.obtainMessage(2);
setTextHandler.sendMessage(msg);
}
};
thread.start();
and your handler look like
private final Handler setTextHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if (thread!= null) {
thread.interrupt();
thread= null;
}
switch (msg.what) {
case 2: //do your work here
Load ld=new Load();
ld.execute();
break;
}
}
};
I have a worker thread and occasionally i send updates to the UI Thread using Handler.Post(). In some cases i need worker thread to wait until Handler.Post() executed on UI Thread and the view is modified and after UI thread is modified, notify the worker Thread to go on...
here is my simple worker thread:
workerThread = new Thread() {
#Override
public void run() {
progressBarHandler.post(new Runnable() {
public void run() {
//Step1: which works ok
ActionModeButton.performClick();
}
}
//Step2: returns null pointer exception because ActionMode
//is not yet created and R.id.select_recording is an
//ActionMode button if I put Thread.sleep(1000); here it
//will work fine.
final View selectRecording = getActivity()
.findViewById(R.id.select_recording);
selectRecording.post(new Runnable() {
public void run() {
selectRecording.performClick();
}
});
}
}
workerThread.start();
using synchronized block with wait and notify
final Handler handler = new Handler();
final Object lock = new Object();
new Thread(new Runnable() {
boolean completed = false;
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
synchronized (lock) {
//Do some stuff on ui thread
completed = true;
lock.notifyAll();
}
}
});
synchronized (lock) {
try {
if(!completed)
lock.wait();
}
catch (InterruptedException e) {
}
}
}
}).start();
What about using a Semaphore for that?
Semaphore semaphore = new Semaphore(0);
uiHandler.post(new Runnable() {
// ... do something here
semaphore.release();
});
semaphore.acquire();
The Semaphore start with 0 permit. The thread will block on semaphore.acquire() until semaphore.release() (which will add a permit) is called.
I am learning via a book and it gives me this example:
Handler handler=new Handler() {
#Override
public void handleMessage(Message msg) {
bar.incrementProgressBy(5);
}
};
and
Thread background=new Thread(new Runnable() {
public void run() {
try {
for (int i=0;i<20 && isRunning.get();i++) {
Thread.sleep(500);
handler.sendMessage(handler.obtainMessage());
}
} catch (Throwable t) {
// just end the background thread
}
}
});
Which works out great. But, further down in the book it says:
If you would rather not fuss with Message objects, you can also pass
Runnable objects to the Handler, which will run those Runnable
objects on the activity UI thread. ...you can use those same methods
on any View (i.e., any widget or container). This slightly simplifies
your code, in that you can then skip the Handler object.
But there are no examples given of how to do this via a Runnable object. Does anyone have an example?
Something like this:
Handler h = new Handler();
Thread background=new Thread(new Runnable() {
public void run() {
try {
for (int i=0;i<20 && isRunning.get();i++) {
Thread.sleep(500);
handler.post(new Runnable() {
public void run() {
bar.incrementProgressBy(5);
}
});
}
}
catch (Throwable t) {
// just end the background thread
}
}
});
As per the Android Docs for Handler:
public final boolean post (Runnable r)
Since: API Level 1 Causes the Runnable r to be added to the message
queue. The runnable will be run on the thread to which this handler is
attached. Parameters
r -- The Runnable that will be executed. Returns
Returns true if the Runnable was successfully placed in to the message
queue. Returns false on failure, usually because the looper processing
the message queue is exiting.