随手记之好问题

1.Toast必须在UI(主)线程使用?

            if (looper == null) {
                // Use Looper.myLooper() if looper is not specified.
                // 调用Looper.myLooper这个函数,
                //也就是会从ThreadLocal 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(主)线程使用”这个说法是不对滴!

你可能感兴趣的:(随手记之好问题)