【问题标题】:HandlerThread: Only one Looper may be created per threadHandlerThread:每个线程只能创建一个 Looper
【发布时间】:2019-05-05 17:12:21
【问题描述】:

这是一个在使用android looper时很常见的问题,但是很奇怪我用的是HandlerThread,而且我从来没有调用过Looper.prepare。不知道为什么会这样。

整个崩溃日志如下:

java.lang.RuntimeException: process_network1

在 com.xiaomi.smarthome.library.common.util.MessageHandlerThread.run(MessageHandlerThread.java:43)

原因:java.lang.RuntimeException:每个线程只能创建一个 Looper

在 android.os.Looper.prepare(Looper.java:92)

在 android.os.Looper.prepare(Looper.java:87)

在 android.os.HandlerThread.run(HandlerThread.java:54)

在 com.xiaomi.smarthome.library.common.util.MessageHandlerThread.run(MessageHandlerThread.java:40)

MessageHandlerThread 如下:

public class MessageHandlerThread extends HandlerThread {

private static final int DUR_TIME = 2 * 60 *60 *1000;
private static final int MSG_EMPTY_MSG = 1;
private Handler mHandler;
public MessageHandlerThread(String name) {
    super(name);
}

public MessageHandlerThread(String name, int priority) {
    super(name, priority);
}

void init() {
    mHandler = new Handler(this.getLooper()) {
        @Override
        public void handleMessage(Message msg) {
            mHandler.sendEmptyMessageDelayed(MSG_EMPTY_MSG, DUR_TIME);
        }
    };

    mHandler.sendEmptyMessageDelayed(MSG_EMPTY_MSG, DUR_TIME);
}

@Override
public synchronized void start() {
    super.start();
    init();
}

@Override
public void run() {
    try {
        super.run();
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(getName(), e);
    }
}
}

它在“super.run();”中崩溃为什么会发生这种情况?似乎进入运行两次?我绝对从不调用“thread.run()

【问题讨论】:

    标签: android handler


    【解决方案1】:

    HandlerThread 正在扩展 Thread 类。

    当你创建一个扩展Thread 的类时,你调用的是start 方法,而不是run 方法。这表示run方法将在内部被start方法调用。

    只需删除super.run() 语句,即可解决您的问题。

    您可以在不扩展 HandlerThread 类的情况下做到这一点,如下所示。

    HandlerThread messageHandlerThread = new HandlerThread("MessageHandlerThread");
    messageHandlerThread.start();
    
    Handler handler = new Handler(messageHandlerThread.getLooper());
    handler.post(<<YOUR_RUNNABLE>>);
    

    【讨论】:

    • 您好,在HandlerThread的run中,有一些初始化,如looper.prepare,notifyAll等,调用start()时会异步调用run()方法。不调用 super.run 是个好主意吗?
    • 是的。如果您查看Looper.prepare 的实现细节,他们正在检查sThreadLocal.get() != null,这意味着如果多次调用Looper.prepare 方法,他们将使用Only one Looper may be created per thread 引发RuntimeException。所以,它不应该在run 中再次调用super.run()
    • 是的,这听起来是解决这个问题的方法,我会试试这个。我只是不知道为什么跑步再次进入。
    • @mianlaoshu,你在代码中使用super.run() 语句再次调用该方法。
    • 我刚刚添加了 if(Looper.myLooper() != null) return;以防止此类崩溃。没有更多的崩溃然后
    猜你喜欢
    • 2019-01-22
    • 2016-03-19
    • 2012-01-16
    • 2011-04-22
    • 2014-05-27
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多