为什么不能通过UI线程的线程访问视图?
我知道没有线程可以访问当前视图,除非它是UI线程。 我想知道为什么? 为什么哪个线程正在改变视图? 这是安全原因吗? 这是我使用的工作:
public void doLayout() { Runnable run = new Runnable() { public void run() { ViewerActivity.setContentView(R.layout.main); } }; handler.post(run); } private Handler handler;'
每次我想改变布局时,这样做都很痛苦。 有不同的工作吗? 我知道异步任务,我从来没有找到一个好方法来使用它,它比我正在做的更好吗? 所有相关的答案都很贴心!
是的,你的权利:为了安全起见,你不能修改另一个线程的视图(这就是为什么它被称为UI线程)。 它可以防止您将UI数据保留在一个不一致的状态,这可能会导致应用程序崩溃并且很难调试。 所以android API只是禁止它(这是一个好主意)。 这是一种常见的UI模式,您可以在大多数API中找到它。
您可以使用post()或runOnUiThread()更新任何视图:
anyView.post(new Runnable() { public void run() { // do update here } });
为什么这种模式?
同步不是免费的。 它会影响性能。 因此,在同一个线程上保持对UI的修改会更容易。
如果我可以修改来自不同线程的数据会发生什么?
例如:线程A
正在改变视图的颜色,而线程B
正在同时读取颜色。 由于multithreading无法保证首先执行哪条指令,因此可能会出现意外结果。 颜色为黑色( 0|0|0
)之前,线程A
想要设置白色( 255|255|255
)并开始将红色组件设置为255
,线程B
开始读取并获得线程A
之前的整个颜色有机会完成并获得红色( 255|0|0
)而不是黑色。
这是一个影响视觉效果的简单示例,但如果某些非常重要的数据发生这种情况,您的应用程序将崩溃,并且这样的错误是如此令人讨厌且难以调试。 关于multithreading有很多值得学习的东西,也许这个java教程是一个很好的起点……
Android应用程序使用单线程模型 ,该线程负责将各种事件分派给UI元素。 这个单线程模型有两个规则:
- 不要阻止UI线程
- 不要从UI线程外部访问Android UI工具包
如果您创建一个在UI thread
外使用View
的UI thread
那么它违反了第二个规则。
安全性不是唯一的UI线程是唯一可以访问视图的线程。 主要原因是视图背后的代码可能不是线程安全的。 这意味着如果您有多个线程读取和写入公共变量,则无法保证数据不会被破坏。
查看这篇伟大的维基百科关于线程安全的文章。