如何从Android AsyncTask中进行活动UI更改?

8
在一个场景中,我有一个UI需要从另一个线程(使用AsyncTask)进行更新。我可以将AsyncTask定义为活动的内部类,但这有两个缺点,我觉得很棘手:
  1. 它使源文件非常大,降低了管理代码的效率
  2. 它使重用线程类变得困难
那么有什么好的解决方案呢?使用内部类,但将其所做的所有内容抽象到其他类中?将对Activity的引用传递给AsyncTask?总是将AsyncTask类定义为内部类,并接受源文件会很大的事实?
3个回答

13

首先要注意的是,在使用 AsyncTask 时,不能在 doInBackground() 中进行 UI 操作。

您可以通过在 doInBackground() 中调用 publishProgress(values) 来更新长时间运行的后台作业的状态。运行时会为这些值调用您的 onProgressUpdate(values) 回调函数,在 UI 线程中执行,从中您可以更新用户界面。

您可以查看例如https://github.com/pilhuhn/ZwitscherA/blob/master/src/de/bsd/zwitscher/TweetListActivity.java#L336以获取示例代码。

可以在自己的类文件中实现 AsyncTask。


doInBackground() 方法无法访问 UI,如果尝试访问,框架会抛出异常。但我的问题更多地涉及 AsyncTask 子类如何访问 UI。 - Ollie C
@Olli,这是我说的:doInBackground()不得访问UI。请使用onPre|PostExecute()在其前面或后面执行,或者通过发布进度在中间执行。这三个回调方法允许访问UI。 - Heiko Rupp

2

我看到的很多例子只是将Context传递到AsyncTask的构造函数中。

public class BackgroundStuff extends AsyncTask<Void, Void, Void> {
    ...
    Context mContext;
    ...
    BackgroundStuff(Context context){
        super();
        this.mContext = context;
    }
    ...
}

我很想听听是否有其他人使用过其他方法。


将上下文传递给类是我目前所做的,这似乎有些混乱,但也许没有更好的方法。 - Ollie C

0

我对AsyncTasks有一种有点奇怪的观点,因为我通常更喜欢使用普通的线程,但基本上我执行后台任务并更新UI的方式是在onCreate()方法的末尾创建一个Handler,然后覆盖handleMessage(Message msg)方法。

然后在我的线程中,我将Handler作为参数传递进去,然后当我希望进行更新时,我会从线程向Handler发送一条消息,现在这样做的作用是从新的后台线程通信到UI线程以处理UI上的工作。

现在我想象AsyncTasks执行类似的任务,但消除了实现覆盖Handlers' handleMessage方法的需要。

学习这两种方法之间的任何优缺点都会很有趣。


我最初使用了Handler,但是我并不太喜欢它,虽然这完全是主观的感受。我喜欢AsyncTask的清晰度,并且通常将它们拆分为单独的类(而不是内部类),这有助于我更好地使用它,并使Activity子类更易于管理。 - Ollie C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接