【问题标题】:Android thread error - Can't create handler inside thread that has not called Looper.prepare()Android 线程错误 - 无法在未调用 Looper.prepare() 的线程内创建处理程序
【发布时间】:2014-09-28 20:19:59
【问题描述】:

我正在尝试让计时器在单独的线程中运行。

我的 onCreate 函数之前有以下声明:

TimerTask scanTask;
Timer t = new Timer();

然后在 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();

但是,当我运行该应用程序时,它会崩溃并给我一个错误: java.lang.RuntimeException:无法在未调用 Looper.prepare() 的线程内创建处理程序

我不确定我是否完全理解为什么会发生此错误。它与UI线程有关吗?另外,我不确定我尝试实现这一点的方式是否正确。这是我第一次尝试在 Android 中处理线程。

【问题讨论】:

  • 尝试输入 Looper.prepare();

标签: java android multithreading


【解决方案1】:

如果您创建一个处理程序(或您调用的任何类创建一个处理程序),它需要位于一个上面有 Looper 并调用 Looper.prepare() 的线程中。 TimerTask 或 CountDownTimer 正在这样做。如何修复它取决于您希望将事件发布到的位置。如果您希望它们在 UI 线程上,则必须在 UI 线程上创建处理程序。如果你想让它们出现在这个线程上,那么你需要在某个时候调用 Looper.prepare 和 Looper.loop。

UI 线程已经有一个 looper(框架会为你启动它),所以在那里创建处理程序总是可以的。

【讨论】:

  • 我想在新线程上发布事件。如果是这种情况,我应该在哪里调用 Looper.prepare() 和 Looper.loop()?
  • 在创建处理程序之前需要调用Prepare。循环应该是线程的最后一条语句,调用后线程只会处理消息,执行永远不会退出循环函数。
【解决方案2】:

你可以像使用HandlerThread一样

HandlerThread handlerThread = new HandlerThread("name");

handlerThread.start();

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

    return true;  
 }
});

【讨论】:

    【解决方案3】:

    我最终稍微更改了代码并决定使用Thread 类:

    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();
        }
    }
    

    onCreate 我使用了以下内容:

    new TimerThread().start();
    

    该程序现在可以正常运行,但现在唯一的问题是在 UI 呈现到屏幕之前程序加载时存在明显的 2-3 秒延迟。

    如果我正在使用的计时器功能在单独的线程上运行,我不确定为什么会发生这种情况,除非我在这里遗漏了什么......

    【讨论】:

    • OsborneCox :我正在做一个非常相似的事情,我需要在线程内使用倒数计时器并且得到像你一样的错误。使用你的代码,确实有效。你能告诉函数looper.Also,一旦倒数计时器工作结束,这个线程是否会自动终止?
    • @Basher51 这里对 Loopers 有很好的解释:stackoverflow.com/questions/7597742/…
    • 创建自己的 Thread 实例比使用 Executors 更复杂
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 2011-10-17
    相关资源
    最近更新 更多