handler.postDelayed is not working in onHandleInte

2019-02-24 23:34发布

问题:

final Handler handler = new Handler();
LOG.d("delay");
handler.postDelayed(new Runnable() {
    @Override public void run() {
        LOG.d("notify!");
        //calling some methods here
    }
}, 2000);

The "delay" does shows in the log, but not others at all. And the method called in the run() is not called at all also. Can anyone help explain why this happens, am I doing anything wrong?

The class that has this code extends IntentService, will this be a problem?

============================

UPDATE: I put this code in the class that extends IntentService. The only place I found it worked was in the constructor. But I need to put it in the onHandleIntent method. So I checked the documentation for onHandleIntent and it said:

This method is invoked on the worker thread with a request to process.Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf.

So based on the result I get, I feel like I cannot use postDelayed in "worker thread". But can anyone explain this a bit more, like why this is not working in worker thread? Thanks in advance.

回答1:

You are using looper of the main thread. You must create a new looper and then give it to your handler.

HandlerThread handlerThread = new HandlerThread("background-thread");
handlerThread.start();
final Handler handler = new Handler(handlerThread.getLooper());
handler.postDelayed(new Runnable() {
    @Override public void run() {
        LOG.d("notify!");
        // call some methods here

        // make sure to finish the thread to avoid leaking memory
        handlerThread.quitSafely();
    }
}, 2000);

Or you can use Thread.sleep(long millis).

try {
    Thread.sleep(2000);
    // call some methods here

} catch (InterruptedException e) {
    e.printStackTrace();
}

If you want to stop a sleeping thread, use yourThread.interrupt();



回答2:

Convert

final Handler handler = new Handler();

to

final Handler handler = new Handler(Looper.getMainLooper());

This worked for me.



回答3:

Handlers and Services will be predictable when the device screen is on. If the devices goes to sleep for example the Handler will not be a viable solution.

A much more better and reliable solution will be to use: AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);



回答4:

IntentService is not designed for such scenario. You can use a regular Service instead. You can put the handler inside the onStartCommand(). Don't forget to call stopSelf() on the Service instance to shut it down after the handler.postDelayed(){}



回答5:

this is how i use handler:

import android.os.Handler;

Handler handler;
//initialize handler
handler = new Handler();

//to start handler
handler.post(runnableName);

private Runnable runnableName= new Runnable() {
        @Override
        public void run() {
            //call function, do something
            handler.postDelayed(runnableName, delay);//this is the line that makes a runnable repeat itself
        }
};