为什么不能通过UI线程的线程访问视图?

时间:2011-10-09 01:34:36

标签: java android ui-thread

我知道没有线程可以访问当前视图,除非它是UI线程。我想知道为什么?为什么哪个线程正在改变视图?这是安全原因吗?这是我使用的工作:

        public void doLayout()
        {
            Runnable run = new Runnable()
            {
                public void run()
                {
                    ViewerActivity.setContentView(R.layout.main);
                }
            };

            handler.post(run);
        }

        private Handler handler;'

每次我想改变布局时,这样做都很痛苦。有不同的工作吗?我知道异步任务,我从来没有找到一个好的方法来使用它,它比我正在做的更好吗?所有相关的答案都很贴心!

3 个答案:

答案 0 :(得分:13)

是的,你的权利:为了安全起见,你不能修改另一个线程上的视图(这就是为什么它被称为UI线程)。它可以防止您将UI数据保留在一个不一致的状态,这可能会使您的应用程序崩溃并且很难调试。所以android API只是禁止这个(这是一个好主意)。这是一种常见的UI模式,您可以在大多数API中找到它。

您可以使用post()runOnUiThread()更新任何视图:

anyView.post(new Runnable() {
    public void run() {
        // do update here
    }
});

为什么会这种模式?
同步不是免费的。它会影响性能。因此,在同一个线程上保持对UI的修改会更容易。

如果我可以修改来自不同线程的数据会发生什么?
例如:线程A正在改变视图的颜色,而线程B正在以相同的时间读取颜色。由于多线程无法保证首先执行哪条指令,因此可能会出现意外结果。颜色为黑色(0|0|0)之前,线程A想要设置白色(255|255|255)并开始将红色组件设置为255,线程B开始阅读并在线程A有机会完成并获得红色(255|0|0)而不是黑色之前获取整个颜色。

这是一个影响视觉效果的简单示例,但如果某些非常重要的数据发生这种情况,您的应用程序将崩溃,并且这样的错误是如此令人讨厌且难以调试。关于多线程有很多东西需要学习,也许this java tutorial是一个很好的起点......

答案 1 :(得分:1)

Android应用程序使用Single Thread Model,此线程负责将各种事件分派给UI元素。此单线程模型有两个规则:

  1. 不要阻止UI线程
  2. 不要从UI线程外部访问Android UI工具包
  3. 如果您创建的线程在View之外使用UI thread,则会违反第二条规则。

答案 2 :(得分:1)

安全性不是唯一的UI线程是唯一可以访问Views的线程。主要原因是视图背后的代码可能不是线程安全的。这意味着如果您有多个线程读取和写入公共变量,则无法保证数据不会被破坏。

查看此great wikipedia article about thread safety.