【问题标题】:Need an explanation : how to use AsyncTask?需要解释:如何使用 AsyncTask?
【发布时间】:2013-03-19 17:18:41
【问题描述】:

我有一个包含一些数据的 XML 文件,所以我创建了一个代表它的类:

public class MyData
{
    ArrayList<SpecialData> list;
    int currentPage, totalPages;
}

您可以猜到我有一个SpecialData 项目列表,每个项目都包含许多字段,currentPage/totalPages 是 XML 文件中的两个唯一值。我需要异步获取和解析 XML 文件,所以我创建了这个类:

class GetXMLTask extends AsyncTask<String, Void, MyData>
{
    @Override
    protected MyData doInBackground(String... params)
    {
        MyData md = null;
        // Getting/parsing data
        return md;
    }
}

我试了一下,问题不是来自这里,因为我正确解析了我的 XML 文件并且我的 MyData 对象是完美的。但是后来我在我的主要Activity 类中使用了这样的任务:

MyData md = null;
GetXMLTask task = new GetXMLTask(this);
task.execute(new String[]{url});
// How can this change my md object?

这可能很愚蠢,但我根本不知道如何将我的 MyData 实例从我的主类链接到我通过 AsyncTask 获得的实例。我该怎么办?谢谢。

【问题讨论】:

  • 为什么不把 MyData 声明为全局变量并尝试在onPostExecute() 中访问它?
  • 听起来你可能想要Future&lt;MyData&gt;
  • 你应该可以只做task.execute(url),而不是new String[]{url}

标签: java android asynchronous android-asynctask


【解决方案1】:

覆盖AsyncTaskonPostExecute 方法:

protected void onPostExecute(MyData result) {
     md = result;
 }

请注意,这假设您的 AsyncTask 是您的活动的内部类。如果不是这种情况,您可以将构造函数中对 Activity 的引用传递给 AsyncTask。在这些情况下,您应该小心使用 WeakReference 到您的 Activity 以防止资源泄漏:

GetXMLTask(MyActivity activity)
{
    this.mActivity = new WeakReference<MyActivity>(activity);
}

protected void onPostExecute(MyData result)
{
     MyActivity activity = this.mActivity.get();
     if (activity == null) // Activity was destroyed due to orientation change, etc.
         return;
     activity.updateUiFromXml(result);
 }

【讨论】:

  • 那么md 是我主要活动中的字段吗?
  • @Rob - 是的,md 将是您希望 doInBackground 的结果所在的位置。当然,您可能希望调用MyActivity 中的方法以使用生成的MyData 更新UI,或者直接在onPostExecute 中进行UI 更新。
  • @ianhanniballake 这很脏...破坏了封装。
  • @Tushar - 我更新了我的答案,在 MyActivity 中调用一个方法来正确封装所有功能,而不是更新公共/包默认范围变量。
  • @ianhanniballake 嗯,我不知道 get 阻塞了 UI 线程。鉴于此,您的解决方案是理想的。 +1
【解决方案2】:

您可能想要实现某种回调。通过这种方式,您可以通过公开访问数据来避免暴露数据,并且您可以实现其他回调(例如在加载数据时出现错误回调)。

例如,您可以定义这样的接口:

interface MyAsyncFinishedLister {
    void onFinished(MyData resultData);
}

你的 AsyncTask 会有一个 MyAsyncFinishedListener 的实例,你可以这样调用 onPostExecute:

protected void onPostExecute(MyData result) {
     myAsyncFinishedListener.onFinished(result);
}

你的主要活动将实现这个接口,看起来像:

class MyActivity extends Activity implements MyAsyncFinishedListener {
    MyData md;

    public void onCreate() {
        super.onCreate();

        GetXMLTask task = new GetXMLTask(this);
        task.execute(new String[]{url});
        task.setOnFinishedListener(this);
    }

    onFinished(MyData result) {
        md = result;
    }
}

【讨论】:

    【解决方案3】:

    如果您希望 AsyncTask 返回一个数据对象,您需要将其存储在类范围内的变量中,而不是函数范围内。为了简单起见,任务通常是一个私有内部类。

    【讨论】:

      【解决方案4】:

      MyData 声明为对整个类可见的变量,并通过将结果分配给MyData 变量来尝试在onPostExecute() 中访问它。

      【讨论】:

        猜你喜欢
        • 2013-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-23
        • 2022-01-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多