Java.lang.RuntimeException:每个线程只能创建一个Looper。

33

我有一个简单的线程,像这样:

public class AwesomeRunnable extends Thread {

    Handler thisHandler = null;
    Handler uihandler = null;
    String update = null;
    long time = 0;

    public AwesomeRunnable(Handler h, long howLong) {
        uihandler = h;
        time = howLong;
    }

    public void run() {
        Looper.prepare();
        thisHandler = new Handler();
  ...

编辑:添加了启动Runnable的代码

public class StartCycle implements Runnable {

    @Override
    public void run() {

        pomodoroLeft = numPomodoro;
        while(pomodoroLeft > 0) {
            pomodoroLeft--;
            actualSeconds = 6 * ONE_SECOND;
            runnable = new AwesomeRunnable(myHandler, actualSeconds);
            runnable.start();
            waitForClock();

这是主要活动的内部类。然而,此线程不在主要活动上运行,而是在运行在主要活动上的另一个线程中运行

无论如何,这个例子与这里完全相同,但由于某种原因,它会给我带来java.lang.RuntimeException: Only one Looper may be created per thread。

我没有在任何地方显式地创建任何其他looper。


1
你可以展示一下启动AwesomeRunnable的代码吗? - fadden
看起来不错。哪一行抛出了异常?哪个线程?(如果你正在终端窗口中查看logcat输出,请使用adb logcat -v threadtime 来显示每行的线程ID)。一些东西一定在同一个线程中创建了两个looper,所以你需要弄清楚它是否在错误的线程中运行,或者在新线程中多次运行。 - fadden
@fadden Looper.prepare(); 抛出了异常。好的...我会尝试按照您建议的方式查看日志输出。 - user3081519
@fadden 实际上错误信息的第一行是:FATAL EXCEPTION: main。这是否意味着它在主线程上以某种方式创建了另一个looper?但为什么呢? - user3081519
听起来它正在尝试这样做。如果两个数字(pid和tid)相同,则肯定是在主线程中尝试创建一个新的Looper。检查堆栈跟踪并查看是谁调用了该函数。 - fadden
2个回答

97

java.lang.RuntimeException: Only one Looper may be created per thread

这个异常被抛出是因为你(或核心的Android代码)已经调用了Looper.prepare()方法来为当前执行的线程创建了一个 Looper。

以下代码检查当前线程是否已经存在一个 Looper,如果不存在,则创建一个 Looper,从而避免了RuntimeException的出现。

    public void run() 
    {
            if (Looper.myLooper() == null)
            {
              Looper.prepare();
            }
            thisHandler = new Handler();

         ....
    }

8
如果您能在代码中提供某种解释,那将非常好。 - Michael
2
简单明了,对我也起作用,非常感谢。 - eyadMhanna
在Android中,无法将代码放入适配器(adapter)的Recycle -> ViewHolder -> view.setOnClickListener中。 - user3402040
3
添加了一份解释。 - Elad Nava
我的Looper,命名真的很有趣。 - Shawn

7

不要仅仅调用Looper.prepare();,首先检查是否对于您的Thread已经存在Looper,如果不存在,则调用该函数。像这样:

if (Looper.myLooper()==null)
    Looper.prepare();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接