美文网首页
Android中子线程真的不能更新UI吗?

Android中子线程真的不能更新UI吗?

作者: plus彭于晏 | 来源:发表于2018-10-09 09:07 被阅读0次

    可借鉴:https://www.cnblogs.com/xuyinhuan/p/5930287.html

    public   class   MainActivity   extends AppCompatActivity {

        private TextView main_tv;

        @Override

        protected   void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.activity_main);

            main_tv = (TextView) findViewById(R.id.main_tv);

            newThread(new Runnable() {

                @Override

                public   void   run() {

                    main_tv.setText("子线程中访问");

                }

            }).start();

        }

    }

    也是很简单的几行,在onCreate方法中创建了一个子线程,并进行UI访问操作。

    点击运行。你会发现即使在子线程中访问UI,程序一样能跑起来。结果如下所示:

    咦,那为嘛以前在子线程中更新UI会报错呢?难道真的可以在子线程中访问UI?

    先不急,这是一个极端的情况,修改MainActivity如下:

    public   class   MainActivity   extends AppCompatActivity {

        private TextView main_tv;

        @Override

        protected   void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.activity_main);

            main_tv = (TextView) findViewById(R.id.main_tv);

            newThread(new Runnable() {

                @Override

                publicvoid run() {

                    try {

                        Thread.sleep(200);

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                    main_tv.setText("子线程中访问");

                }

            }).start();

        }

    }

    让子线程睡眠200毫秒,醒来后再进行UI访问。

    结果你会发现,程序崩了。这才是正常的现象嘛。抛出了如下很熟悉的异常:

    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

    at android.view.ViewRootImpl.checkThread(ViewRootImpl.Java:6581)

    at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:924)

    ……

    在onCreate()方法里面可以,在onCreate()新建一个子线程,我们发现程序并不会崩溃,正常运行,但是当我们让这个线程休眠2秒,或者更长时间。这时程序崩溃了。

    这时我们是不是在想不是在子线程都不能更新UI的吗,怎么在onCreate()方法里面竟然可以正常运行?

    答案:ViewRootImpl的创建在onResume方法回调之后,而我们一开篇是在onCreate方法中创建了子线程并访问UI,在那个时刻,ViewRootImpl是没有创建的,无法检测当前线程是否是UI线程,所以程序没有崩溃一样能跑起来,而之后修改了程序,让线程休眠了200毫秒后,程序就崩了。很明显200毫秒后ViewRootImpl已经创建了,可以执行checkThread方法检查当前线程。

    这篇博客的分析如题目一样,Android中子线程真的不能更新UI吗?在onCreate方法中创建的子线程访问UI是一种极端的情况,这个不仔细分析源码是不知道的。

    第二种说法:子线程检查方法checkThread()在ViewRootImpl中被调用,而ViewRootImpl在handleResumeActivity时被添加,也就是对应的是onResume()。所以也就是说在onCreate时根本不会执行checkThread()方法。

    作者:MDove

    链接:https://juejin.im/post/5b4563dee51d45190e34e531

    来源:掘金

    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    相关文章

      网友评论

          本文标题:Android中子线程真的不能更新UI吗?

          本文链接:https://www.haomeiwen.com/subject/cvzsaftx.html