子线程不能UI绘制,但可以弹toast

//2023.12.12,本是比较简单的记录了一下,挺意外好几位收藏或点赞,所以补充一些,让内容详细点

使用子线程弹Toast,需要该子线程有Looper,不然会报错,比如我的代码是

        new Thread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this,"test1",Toast.LENGTH_LONG).show();
            }
        }).start();

报错如下,这个是android7.1打印的堆栈

12-12 16:35:45.058  2250  2271 E AndroidRuntime: FATAL EXCEPTION: Thread-2
12-12 16:35:45.058  2250  2271 E AndroidRuntime: Process: com.example.administrator.myapplication, PID: 2250
12-12 16:35:45.058  2250  2271 E AndroidRuntime: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
12-12 16:35:45.058  2250  2271 E AndroidRuntime:        at android.os.Handler.<init>(Handler.java:200)
12-12 16:35:45.058  2250  2271 E AndroidRuntime:        at android.os.Handler.<init>(Handler.java:114)
12-12 16:35:45.058  2250  2271 E AndroidRuntime:        at android.widget.Toast$TN$2.<init>(Toast.java:336)
12-12 16:35:45.058  2250  2271 E AndroidRuntime:        at android.widget.Toast$TN.<init>(Toast.java:336)
12-12 16:35:45.058  2250  2271 E AndroidRuntime:        at android.widget.Toast.<init>(Toast.java:103)
12-12 16:35:45.058  2250  2271 E AndroidRuntime:        at android.widget.Toast.makeText(Toast.java:256)
12-12 16:35:45.058  2250  2271 E AndroidRuntime:        at com.example.administrator.myapplication.MainActivity$2.run(MainActivity.java:258)
12-12 16:35:45.058  2250  2271 E AndroidRuntime:        at java.lang.Thread.run(Thread.java:761)

这个是android11打印的堆栈

01-01 20:51:21.694  7241  7268 E AndroidRuntime: FATAL EXCEPTION: Thread-2
01-01 20:51:21.694  7241  7268 E AndroidRuntime: Process: com.example.administrator.myapplication, PID: 7241
01-01 20:51:21.694  7241  7268 E AndroidRuntime: java.lang.NullPointerException: Can't toast on a thread that has not called Looper.prepare()
01-01 20:51:21.694  7241  7268 E AndroidRuntime:        at com.android.internal.util.Preconditions.checkNotNull(Preconditions.java:157)
01-01 20:51:21.694  7241  7268 E AndroidRuntime:        at android.widget.Toast.getLooper(Toast.java:179)
01-01 20:51:21.694  7241  7268 E AndroidRuntime:        at android.widget.Toast.<init>(Toast.java:164)
01-01 20:51:21.694  7241  7268 E AndroidRuntime:        at android.widget.Toast.makeText(Toast.java:492)
01-01 20:51:21.694  7241  7268 E AndroidRuntime:        at android.widget.Toast.makeText(Toast.java:480)
01-01 20:51:21.694  7241  7268 E AndroidRuntime:        at com.example.administrator.myapplication.MainActivity$2.run(MainActivity.java:258)
01-01 20:51:21.694  7241  7268 E AndroidRuntime:        at java.lang.Thread.run(Thread.java:923)

原因是相同的,需要该线程有Looper

android11上,在Toast.java中直接检查当前线程的Looper是否为空

         return checkNotNull(Looper.myLooper(),
                  "Can't toast on a thread that has not called Looper.prepare()");

android7.1上,在Toast.java中需要创建handler

final Handler mHandler = new Handler() 

在Handler.java中,会获取当前线程的Looper,并判断是否为空

         mLooper = Looper.myLooper();
             if (mLooper == null) {
                  throw new RuntimeException(
                        "Can't create handler inside thread that has not called Looper.prepare()");
            }

添加个 Looper.prepare();不再报错,但也不会弹toast

        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(MainActivity.this,"test1",Toast.LENGTH_LONG).show();
            }
        }).start();

再加上 Looper.loop();就可以正常弹toast了,这是因为Toast.java中显示toast是在handleMessage中处理的,不执行Looper.loop();消息不会送到handleMessage中处理

        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(MainActivity.this,"test1",Toast.LENGTH_LONG).show();
                Looper.loop();
            }
        }).start();

Looper.loop为死循环,阻塞,上面的方法只能该线程执行时弹一次toast,如果要多次弹toast,或某个条件达到让弹toast,最好把Toast.makeText()放在handleMessage中

        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                threadHandler = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        Log.d(TAG,"make a toast");
                        Toast.makeText(MainActivity.this,"test",Toast.LENGTH_LONG).show();
                    }
                };
                Looper.loop();
            }
        }).start();

参考文章:https://blog.youkuaiyun.com/tiangaopan/article/details/104791015/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值