1.Toast必须在UI(主)线程使用?
if (looper == null) {
// Use Looper.myLooper() if looper is not specified.
// 调用Looper.myLooper这个函数,
//也就是会从ThreadLocal<Looper> sThreadLocal 去获取当前线程的looper。
looper = Looper.myLooper();
if (looper == null) {
// 没有获取到当前线程的looper的话,就会抛出这个异常
// 而在子线程中创建了looper就不会抛出异常了。
throw new RuntimeException(
"Can't toast on a thread that has not called Looper.prepare()");
}
}
// 当looper里面有Message的时候会将message取出来,
// 然后会通过handler的handleMessage来处理。
mHandler = new Handler(looper, null) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW: // 显示
case HIDE: // 隐藏
case CANCEL: // 取消
}
}
};
1.从创建TN的实例,并传入looper,此时的looper还是null。
2.进入TN的构造函数可以看到会有looper是否为null的判断,并且在当looper
为null时,会从当前线程去获取looper(Looper.myLooper())
,如果还是获取不到,会抛出这个异常信息:Can't toast on a thread that has not called Looper.prepare()。
3.而有同学会误会只能在UI线程toast的原因是:UI(主)线程在刚创建的时候就有创建looper的实例
了,在主线程toast的话,会通过Looper.myLooper()获取到对应的looper,所以不会抛出异常信息
。
4.而不能直接在子线程程中toast的原因是:子线程中没有创建looper
的话,去通过Looper.myLooper()获取到的为null,就会throw new RuntimeException
(
"Can't toast on a thread that has not called Looper.prepare()");
综上,“Toast必须在UI(主)线程使用”这个说法是不对滴!