使用方法
实例化一个handler对象
val handler = object : Handler() {
override fun handleMessage(msg: Message) {
Log.e(TAG, "收到消息:" + msg.obj.toString())
super.handleMessage(msg)
}
}
在需要发送消息的地方这样调用
val msg = Message()
msg.obj = "一条消息"
handler.sendMessage(msg)
打印日志
我们一般是在主线程创建handler,子线程发消息,比如我们可以这样写
object : Thread() {
override fun run() {
super.run()
val msg = Message()
msg.obj = "子线程消息"
handler.sendMessage(msg)
}
}.start()
打印日志
有时候可能需要在子线程创建handler,主线程发消息,我们可能会这样写
class HandlerTestActivity : AppCompatActivity() {
val TAG = "HandlerTestActivity"
var handler:Handler?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_handler_test)
object : Thread() {
override fun run() {
super.run()
Looper.prepare()
handler = object : Handler() {
override fun handleMessage(msg: Message) {
Log.e(TAG, "收到消息:" + msg.obj.toString())
super.handleMessage(msg)
}
}
Looper.loop()
}
}.start()
}
//按钮点击事件,点击后发送消息
fun sendMessage(view: View) {
val msg = Message()
msg.obj = "主线程消息"
handler?.sendMessage(msg)
}
}
运行代码后,点击按钮会得到如下报错
我们根据报错信息,到源码中寻找报错的原因,发现在Handler的构造方法中,有这个报错信息的代码
public Handler(@Nullable 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 " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
可以看出,当mLooper为null时,就会抛出这个错误,mLooper是通过Looper.myLooper()获取的,
我们找到Looper.myLooper()方法
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
发现是调用了sThreadLocal的get()方法获取的,而sThreadLocal是一个ThreadLocal对象,持有Looper的范型
@UnsupportedAppUsage
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
他的get方法是这样的
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
简单点说,就是从一个Map里取出一个T对象,也就是上面的范型Looper
有get就有set,set方法是这样的
public void set(T value) {
Thread