Can‘t create handler inside thread that has not called Looper.prepare()
Posted 阳光照不到的王国
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Can‘t create handler inside thread that has not called Looper.prepare()相关的知识,希望对你有一定的参考价值。
android开发过程中,如果在子线程中创建Handler时会出现下面这种异常。
Can't create handler inside thread that has not called Looper.prepare()
下面根据源码来解读下出现这个问题的原因
Handler所在的目录位置
/frameworks/base/core/java/android/os/Handler.java
1、Handler的构造函数
public Handler() {
//注释1
this(null, false);
}
//注释2
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());
}
}
//注释3
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;
}
注释1:在new Handler()时会调用注释2处的两个参数的构造函数。
下面观察注释3处,通过Looper.myLooper()来获取mLooper对象,如果mLooper对象为空则抛出此文章开头时出现的异常。
2、查看Looper.myLooper()函数做了什么。
Looper类对应Android源码目录如下
/frameworks/base/core/java/android/os/Looper.java
返回一个与当前线程关联的Looper对象,如果当前线程未关联Looper则返回null。
继续查看sTheadLocal。如果没有调用prepare()的话,sTheadLocal.get()将会返回null
看下prepare()函数
根据源码可以看出,调用prepare()函数之后才会调用sThreadLocal.set(Looper)。
走到这个步骤之后也就基本破案了,解决方法也一目了然。就是在子线程中创建Handler之前要调用一下Looper.prepare();
以上是关于Can‘t create handler inside thread that has not called Looper.prepare()的主要内容,如果未能解决你的问题,请参考以下文章