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

原创 2017年01月03日 11:09:37

我们都知道在非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了,



版权声明:本文为博主原创文章,未经博主允许不得转载。

在工作线程中处理UI线程报错:Only the original thread that created a view hierarchy can touch its views.

如果将更新UI控件的代码写入到工作线程中便会报错, 例子如下: Runnable socketRun = new Runnable() { @Override public void ru...
  • shenyuemei
  • shenyuemei
  • 2013年09月04日 10:19
  • 16929

Android异常:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original

Android异常:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that cr...
  • qq_32059827
  • qq_32059827
  • 2016年06月16日 09:21
  • 2693

android.view.ViewRoot$CalledFromWrongThreadException 异常的解决方案 * 更新时间: 2011-07-21

在android平台下,进行多线程编程时,经常需要在主线程之外的一个单独的线程中进行某些处理,然后更新用户界面显示。但是,在主线线程之外的线程中直接更新页面显示的问题是:系统会报这个异常,androi...
  • Vincent_czz
  • Vincent_czz
  • 2011年12月14日 14:32
  • 40567

Android进阶——Handler的应用之解决Only the original thread that created a view hierarchy can touch its views

解决错误:Only the original thread that created a view hierarchy can touch its views。
  • CrazyMo_
  • CrazyMo_
  • 2017年01月05日 15:57
  • 9938

错误:Only the original thread that created a view hierarchy can touch its views——Handler的深入解析

这个错误很常见,基本上写线程操作都遇到过这个错误。根本原因是view控件的线程安全问题,通俗点讲就是所有的更新UI操作都需要在主线程(也就是UI线程中完成),而不能在新开的子线程中操作。 基本思...
  • zsg2063
  • zsg2063
  • 2014年05月12日 16:45
  • 1411

Handler: 更新UI的方法

总是感觉 android 中 UI 更新很让人纠结!自己小结一下,算是抛砖引玉。读这篇文章之前,假设你已经明白线程、Handler 的使用。 在文章的最后,附录一张草图,主要用于说明 Handle...
  • AndroidBluetooth
  • AndroidBluetooth
  • 2011年05月02日 15:42
  • 37749

Android Only the original thread that created a view hierarchy can touch its views.

解决方法 :
  • aikongmeng
  • aikongmeng
  • 2014年05月04日 16:52
  • 1083

Android 积累一些常见的开发异常与问题

1.使用PullToRefresh库的时候,想让其自动刷新(setRefreshing)不起效果     下面的解决方式,当设定的时间小的时候,同样也会导致刷新失败(这里设置了1000ms) /...
  • Coder_Hcy
  • Coder_Hcy
  • 2017年05月09日 10:34
  • 297

android开发步步为营之56:Android开发常见问题技术点总结之一

android开发过程中常见问题技术点总结
  • figo0423
  • figo0423
  • 2015年04月27日 15:02
  • 1445

android在工作线程中处理UI线程报错:Only the original thread that created a view hierarchy can touch its views.

解决办法:异步更新UIandroid要求只能在UI线程中更新UI,要想在其他线程中更新UI,就需要异步来处理。Android异步更新UI的四种方式:1.使用Handler消息传递机制; 2.使用As...
  • beibaokongming
  • beibaokongming
  • 2017年05月03日 16:28
  • 733
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy
举报原因:
原因补充:

(最多只允许输入30个字)