异常:java.lang.RuntimeException:Can't create handler inside thread that has not called Looper.prepare

本文探讨了在Android开发中使用okHttp发起网络请求时遇到的问题:无法直接在子线程中使用Toast显示信息。文章详细介绍了问题的原因,并提供了两种解决方案:利用runOnUiThread()方法和Handler机制来实现在子线程中更新UI的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在使用okHttp发送一个请求时,由于需要查看返回的信息,便想用Toast显示该信息,没想到报错了:
这里写图片描述
究其原因,原来是因为okHttp发送请求时新开了一个子线程,而Toast消息不能在子线程中弹出,故有此报错。

问题原因

Android中的UI是线程不安全的,因此要更新UI必须在主线程中进行。
有两种更新UI的方法,一种是runOnUIThread,另一种是Handler().post(),顺便学习一下这两者的区别吧。

解决方案

  • runOnUiThread(Runnable action)
     //源码
     /**
     * Runs the specified action on the UI thread. If the current thread is the UI
     * thread, then the action is executed immediately. If the current thread is
     * not the UI thread, the action is posted to the event queue of the UI thread.
     * 在UI线程中执行特定操作。如果当前线程是UI线程,则操作将马上执行。
     * 反之则将操作发送到UI线程的事件队列等待执行。
     * @param action the action to run on the UI thread
     */
    @Override
    public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }

在网上查阅资料后,发现如下的一段话:

runOnUiThread is basically suited to show a progress dialog or do some UI manipulations before an AsyncTask call. If you want to update the UI in the middle of a thread execution, then the best approach is to create a Handler which will update your UI, and let the thread continue running, for example, updating a text view periodically after a few sec, say timer functionality.

意思是说如果想在异步线程前执行某些UI操作(如更新progressBar进度),适合用runOnUiThread方法;
但如果想在线程中执行UI操作,还是推荐用Handler。

注意:runOnUiThread()是Activity中的方法,所以使用时应指明所在Activity,例如:

 MainActivity.this.runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(MainActivity.this, "UI action in UI Thread", Toast.LENGTH_LONG).show();
                                }
                            });
  • 使用Thread+Handler处理
public static final int UPDATE_UI=1;

Handler handler=new Handler(){
    public void handleMessage(Message msg){
        switch(msg.what){
            case UPDATE_UI:
            //此处进行UI操作
            ...
        }
    }
});

new Thread(new Runnable(){
    @Override
    public void run(){
    Message message=new Message();
    message.what=UPDATE_UI;
    handler.sendMessage(message);
    }
});

或使用Handler(Looper.getMainLooper())

private void toastTest() {
        new Thread(new Runnable() {

            @Override
            public void run() {
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {

                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this, "UI action in UI Thread", Toast.LENGTH_LONG).show();
                    }
                });
            }
        }).start();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值