1
votes

I am trying to get a timer to run in a separate thread.

I have the following declaration before my onCreate function:

TimerTask scanTask;
Timer t = new Timer();

Then the following code within onCreate:

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        scanTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("timer test");
            }
        };

        t.schedule(scanTask, 0, 5000);

        CountDownTimer waitTimer;
        waitTimer = new CountDownTimer(20000,300) {
            @Override
            public void onTick(long l) {
            }
            @Override
            public void onFinish() {
                t.cancel();
                System.out.println("Timer stopped");
            }
        }.start();
    }
}; 

Thread periodic_scan = new Thread(runnable);
periodic_scan.start();

However, when I run the app, it crashes and gives me the error: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

I'm not sure I completely understand why this error is occurring. Is it something to do with the UI thread? Also, I'm not sure whether the way I've tried to implement this is correct. This is my first time trying to deal with threads in Android.

3
try typing Looper.prepare();Nabin

3 Answers

1
votes

you can use HandlerThread like

HandlerThread handlerThread = new HandlerThread("name");

handlerThread.start();

Handler threadHandler = new Handler(handlerThread.getLooper(),new Callback() {
    public boolean handleMessage(Message msg) {

    return true;  
 }
});
1
votes

I ended up changing the code a bit and decided to use a Thread class:

class TimerThread extends Thread {

    TimerTask scanTask;
    Timer t = new Timer();

    @Override
    public void run() {
        Looper.prepare();
        scanTask = new TimerTask() {
            public void run() {
                System.out.println("timer test");
            }
        };

        t.schedule(scanTask, 0, 5000);

        CountDownTimer waitTimer;
        waitTimer = new CountDownTimer(20000,300) {
            @Override
            public void onTick(long l) {

            }

            @Override
            public void onFinish() {
                t.cancel();
                System.out.println("Timer stopped");
            }
        }.start();

        Looper.loop();
    }
}

In onCreate I used the following:

new TimerThread().start();

The program now works without any errors, however the only problem now is that there is a noticeable 2-3 second lag when the program loads up before the UI renders to the screen.

I'm not sure why this is happening if the timer function I am using is running on a separate thread, unless I've missed something here...

0
votes

If you create a handler (or any class you call creates a handler) it needs to be in a Thread that has a Looper on it, and has called Looper.prepare(). Either TimerTask or CountDownTimer is doing that. How to fix it depends on where you want the events to be posted to. If you want them on the UI thread, you'll have to create the handler on the UI thread. If you want them on this thread, then you need to call Looper.prepare and Looper.loop at some point.

The UI thread already has a looper (the framework starts it for you) so its always ok to make handlers there.