【问题标题】:Return Multiple Data from AsyncTask从 AsyncTask 返回多个数据
【发布时间】:2013-09-15 09:59:13
【问题描述】:

我正在尝试组织我的应用程序代码,将 AsyncTask 类与 Activity 或 Fragments 分开。 通过浏览这个论坛,我了解到“接口和监听器”解决方案:

Interface.java

public interface TaskCompleteListener<T> {
    public void onTaskComplete(T result);
}

AsyncTask.java

[...]
@Override
protected void onPostExecute(String JSONResponse) {
    // using Gson library I convert JSONResponse string to POJO objects...
    listener.onTaskComplete(result);
}

Activity.java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    // start AsyncTask...
    }

    // Inner class implementing interface
    public class LoadTaskCompleteListener implements TaskCompleteListener<Object> {
        @Override
        public void onTaskComplete(Object result) {
            updateUI(result);
        }
    }

    public void updateUI(Object result) {
    // here you can manage UI updating, using result object
    }
}

更新 DataHelper.java

public class DataHelper {

    private AsyncTaskCompleteListener<Object> listener;

    public DataHelper(AsyncTaskCompleteListener<Obejct> listener) {
        this.listener = listener;
    }

    // Multiple AsyncTask are defined here...
}

好吧,我非常喜欢这种模式,但是:如果内部活动(或片段) 我有多个请求,具有不同类型的结果(单个对象、数组、列表) 以及管理它们的不同业务逻辑? 我无法使用单个回调来处理这个问题。有任何想法吗?我应该添加多个 接口内部的回调?我真的坚持这一点。 我有一个名为 DataHelper 的文件,里面有多个 AsyncTask(类似于 web getter)。 如果您提出任何其他选择,我自然可以放弃这种方法。

【问题讨论】:

  • 你能在你发起listener的地方发布代码吗?
  • 查看更新编辑。我将它传递给 DataHelper 构造函数,这是一个用于数据检索的便利类。

标签: java android android-fragments android-asynctask android-activity


【解决方案1】:

为什么不返回一个对象数组作为结果呢?然后,如果您在该数组中有多个对象,您将知道放置它们的顺序,因此您可以一次使用多个结果集。

public interface TaskCompleteListener<T> {
    public void onTaskComplete(T... results);
}

【讨论】:

  • 感谢您的回复,有趣的想法,但这样我必须等待所有请求完成,然后才能处理结果,对吗?
  • 如果您像这样一次将它们全部归还,那么是的,您必须等待它们全部完成。
【解决方案2】:

请注意,可以使用“处理程序”代替异步任务,并且每个处理程序都可以将其消息返回到消息循环器,其中 msg 包装不同的数据。易于处理许多数据类型,因为它只是一个消息组件。 示例here

参见“process_entity()”,其中包含结果组件的消息由示例代码发送。

【讨论】:

【解决方案3】:

注意onTaskComplete() 的定义接受一个泛型类型作为参数,类型T

 onTaskComplete(T result);

这意味着你可以传入任何对象类型、单个对象、数组、列表等。

关于如何使用单个回调处理不同的结果,您可以使用Bundle 将结果放入其中,与一个键关联,然后在updateUI() 中检查该键并采取适当的措施。

类似这样的东西(伪代码,不确定它是否会编译):

@Override
protected void onPostExecute(String JSONResponse) {
    Bundle bundle = new Bundle();
    bundle.putString("key_json_response", result); //put the response in a Bundle
    listener.onTaskComplete(bundle);
}

// .....
public void updateUI(Object result) {
   Bundle bundle = (Bundle)result;
   if(bundle.containsKey("key_json_response")){
     String json = bundle.getString("key_json_response");
     // process json
   } else if(bundle.containsKey("key_another_response")){
     // process another response
   } 
}

【讨论】:

  • 听起来不错...我只是想避免将诸如 JSON 解析之类的业务逻辑移动到活动中,提供它可以使用的对象。
  • 没有什么可以阻止你这样做。您可以在onPostExecute() 中解析json,然后将准备使用的对象放入Bundle,而不是放入String json 响应。如果它们实现了Serializable,您可以使用Bundle 来放入任何原始数据类型以及自定义对象。
  • 你是对的。我使用了 bundle.putSerializable 方法来传递一个通用的 Bundle 对象。使用 Parcelable 接口更好吗?总的来说,您认为我的代码组织方法会运作良好吗?
  • 一般推荐Parcelable 支持Serializable,主要增益是速度。但是,使用Serializable 要简单得多。是的,使用接口从AsyncTask 传递结果的方法很好。
猜你喜欢
  • 2012-02-13
  • 2011-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多