为什么子线程弹Toast报错及为什么Handle需要Loop对象

为什么子线程弹Toast报错及为什么Handle需要Loop对象

弹出错误:java.lang.RuntimeException: Can’t toast on a thread that has not called Looper.prepare()

1
Toast.makeText(et_input.getContext(),"测试",Toast.LENGTH_LONG).show();;

1.Toast.makeTest调用构造函数会创建个TN对象,这个对象需要Loop,Loop为空,并且当前线程的loop也是空的就会抛错

1
2
3
public Toast(@NonNull Context context, @Nullable Looper looper) {
mContext = context;
mTN = new TN(context.getPackageName(), looper);
1
2
3
4
5
6
7
8
9
10
TN(String packageName, @Nullable Looper looper) {
...
if (looper == null) {
// Use Looper.myLooper() if looper is not specified.
looper = Looper.myLooper();
if (looper == null) {
throw new RuntimeException(
"Can't toast on a thread that has not called Looper.prepare()");
}
}

2.提示也很明细,从源码看也可以看到是少了loop对象
所以只需要在生成Toast对象之前,创建loop对象Looper.prepare(),并且最后开启循环 Looper.loop()

注意必须开启循环Loop.loop(),否则消息无法弹出

1
2
3
Looper.prepare();
Toast.makeText(et_input.getContext(),"测试",Toast.LENGTH_LONG).show();
Looper.loop();

3.为什么一定要Loop ,是因为源码中有用到Handler ,handler 必须要有个loop对象的

而且handler会关联Loop当中的mQueue对象,用来发消息,比如sendMessageDelayed 最终会通过mQueue对象发送消息,loop对象收到消息,会回调mQueue对象关联的loop对象的handleMessage(Message msg)的接口,完成消息通信.

1
2
3
4
5
6
7
8
9
10
11
12
13
public Handler(Callback callback, boolean async) {
...

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;
}