在Thread中创建Handler报错

最近面试,总会面到在线程中可以new一个Handler吗?

答案是:不能。

会抛出异常:java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

分析:请看源码

第一步:Handler构造方法

public Handler(Callback callback, boolean async) {
    if (FIND_POTENTIAL_LEAKS) {
        final Class<? extends Handler> klass = getClass();
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                (klass.getModifiers() & Modifier.STATIC) == 0) {
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                klass.getCanonicalName());
        }
    }

    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    mQueue = mLooper.mQueue;
    mCallback = callback;
    mAsynchronous = async;
}

因为Looper的mLooper()返回为空,所以抛出异常。

第二步:查看Looper的myLooper()方法

public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

返回sThreadLocal.get(),需要查找查找sThreadLocal.set()

第三步:查找sThreadLocal.set()方法

private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

看到关键的代码sThreadLocal.set(new Looper(quitAllowed))。也就是说,只有Looper的prepare()被调用的时候,此时才会返回一个Looper对象。Looper.myLooper()才不会返回null。

 

上一篇:Looper.getMainLooper()使用误区


下一篇:android 消息机制