android - 在 doInBackground 的 AsyncTask 中更改 UI 线程的 View ,并不总是抛出 CalledFromWrongThreadException

标签 android android-asynctask android-view

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/

相关文章:

Android 切换按钮/分段按钮

android - 使用 openwith 选项 android 打开 pdf

Android postDelayed方法可靠性

java - 设置AsyncTask调用其他方法

android - 在单独的线程中填充 ListView

java - 为什么 AsyncTask 在添加新数据后不自动更新 GraphView?

android - 在自定义 View 类中的何处设置自定义字体(扩展按钮)?

Android Wear CircledImageView(和 DelayedConfirmationView)总是方形

java - 从父类(super class)访问 View

java - 如何在Android中创建 'Always on top overlay'