AsycnTask 中的以下代码:
@Override
protected Boolean doInBackground(View... params) {
try{
Drawable drawPhoto = DataDatero.ImageDownload(taskPhotoName);
((ImageView)params[0]).setImageDrawable(drawPhoto);
((TextView)params[1]).setText(taskItemListText);
((TextView)params[2]).setTextColor(taskColore);
((TextView)params[2]).setText(taskItemStockText);
[...]
}
抛出 CalledFromWrongThreadException ,描述:
Only the original thread that created a view hierarchy can touch its views
这已经在很多问题中进行了讨论:example , 另一个 example ;并且都得出相同的结论。
但我得到的不仅仅是异常..
我从 List 适配器中的 getView 中调用 execute,图像 (params[0]) 在 View 中更新,同时为文本抛出异常。另外,如果我只保留 textview updates ,文本会更新并且不会抛出异常。
如果我先更新 TextView,然后更新 ImageView,一些文本和图像会更新,而另一些图像不会更新(imageDownload 包括 2-3 秒的网络操作)
为什么有的更新了有的没有?
注意:仅在 api 16 仿真上使用 sdk 4.0、v4 支持进行了测试。 我修好了它,我没有触及 doInBackground 中的 View 第二个示例是类似的...如果 onCreate 未完成,操作是否得到验证?
最佳答案
我遇到过类似的问题,问了一个问题here (经过大量挖掘后 self 回答)。
从本质上讲,它可以归结为,与每个人的想法相反,您可以从 AsyncTask
execute()
修改 UI 元素如果那些 View 还没有经过布局遍历。这与主要执行流程( Activity 生命周期方法/回调)异步发生,因此如果有问题的 View
是在 execute()
被调用之前不久创建的,您 可以访问它们(意思是,不会抛出异常,这当然仍然是非常糟糕的做法,不可取)。因为 execute()
发生在另一个线程上,布局遍历(在 UI 线程上运行)可能会在您的 execute()
运行时完成,这解释了为什么只有一些 View 可能被修改,其他人抛出异常。它还解释了为什么“只保留 textview 更新”(并且可能删除 ImageView
更新)导致这些更新也“神奇地”工作。由于这是一个与时间相关的问题,它取决于许多因素,其中包括 Drawable drawPhoto = DataDatero.ImageDownload(taskPhotoName);
需要多长时间才能运行。
PS:我意识到这是一个迟到的答案,但我认为这对于第一个找到这个答案的人很有用,处理此类问题的帖子并不多。
关于android - 在 doInBackground 的 AsyncTask 中更改 UI 线程的 View ,并不总是抛出 CalledFromWrongThreadException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13882786/