ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy

我们都知道在非UI线程不能对UI进行操作,比如下面的操作 

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        tv.setText( "I'm strong");
                    }
                }).start();
            }
        });

就会出现上面的错误,这里介绍下对于上面的错误解决方法:

1.通过Activity.runOnUiThread(Runnable)方法解决:

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Activity.this.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                tv.setText( "I'm strong");
                            }
                        });

                    }
                }).start();
            }
        });

延时的话就的用handler 了;因为主线程不能阻塞,5秒就ANR。

2.和1的原理是一样的,就是通过Handler,

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                       mhandler.sendEmptyMessage(0);
                    }
                }).start();
            }
        });


Handler mhandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            tv.setText( "I'm strong");
        }
    };
3.通过View.post(Runable),这个View就是要操作的View,如果要延时的话用 View.postDelayed(Runnable, long)

findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        tv.post(new Runnable() {
                            @Override
                            public void run() {
                                tv.setText( "I'm strong");
                            }
                        });
                    }
                }).start();
            }
        });

上面的1.3方法看着代码有些恶心 (当然上面的那种2b操作一般是不会出现的,我主要是投方便的,你可以把那个I'm strong 数据信息的来源想象成从网络请求这种阻塞UI线程的操作而来的),这个时候你可以用2来简化代码,或者使用Asynctask,

4.还有一种就是通过AsyncTask,

这个怎么说呢,我是个偷懒的人,所以直接拖官方的解释吧,传送门https://developer.android.com/guide/components/processes-and-threads.html#Threads

AsyncTask 允许对用户界面执行异步操作。 它会先阻塞工作线程中的操作,然后在 UI 线程中发布结果,而无需您亲自处理线程和/或处理程序。

要使用它,必须创建 AsyncTask 的子类并实现 doInBackground() 回调方法,该方法将在后台线程池中运行。 要更新 UI,应该实现 onPostExecute() 以传递 doInBackground() 返回的结果并在 UI 线程中运行,以便您安全地更新 UI。 稍后,您可以通过从 UI 线程调用 execute() 来运行任务。

主要代码
public void onClick(View v) {
    new TvSetTextTask().execute("I'm strong");
}

private class TvSetTextTask extends AsyncTask<String, Void, String> {
    /** The system calls this to perform work in a worker thread and
      * delivers it the parameters given to AsyncTask.execute() */
    protected String doInBackground(String... urls) {
        return urls[0];
    }


      * the result from doInBackground() */
    protected void onPostExecute(String result) {
        tv.setText(result);
    }
}



ok了,



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值