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

2018-10-09  本文已影响0人  plus彭于晏

可借鉴: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

来源:掘金

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

上一篇下一篇

猜你喜欢

热点阅读