一个AsynckTask的多个回调

时间:2017-02-03 08:52:27

标签: java android android-fragments android-asynctask

我正在编写一个应用程序,其中我在ViewPager中有不同的片段。在每个片段中,我使用几个AsyncTask从Web服务器获取数据。一些片段需要调用相同的AsynTask(服务),但如果其中一个已经调用它,因为服务需要一段时间来响应,我想防止调用它,但我想让AsyncTask发送导致所有称之为碎片的碎片。当用户更新片段时,我还需要更新所有片段中的de数据(SwipeToRefresh即)。我今天拥有的函数是一个函数,我验证服务是否已被调用,如果不是这样,保存一个标志来指示服务被调用,并使用AsyncTask调用服务,该函数接收回调接口以发送结果是请求Fragmnet,如果在另一方面,服务已被调用,则将Callback添加到Callback列表,稍后在AsyncTask.onPostExecute中遍历该列表以将resull发送到所有fragmnet。

最大的问题是,当我发出多个请求时,就像用户在一段时间后打开应用程序一样,导致内存泄漏(GC工作太多而应用程序冻结)并且应用程序终止。它也没有解决在一次调用中更新所有片段的问题。

这是我之前提到过的代码(只是一个例子):

public class Test {

private static List<Integer> calledServices = new ArrayList<>();
private static Map<Integer, List<Callback>> callbacksMap = new HashMap<>();

public static void call(int serviceId, Callback callback) {
    if (!hasBeenCalled(serviceId)) {
        calledServices.add(serviceId); //saves flag
        ServiceAsyncTask task = new ServiceAsyncTask(serviceId, callback);
        task.execute();
    } else {
        callback.onPreExecute();
        if (callbacksMap.containsKey(serviceId)) {
            callbacksMap.get(serviceId).add(callback);
        } else {
            List<Callback> callbacks = new ArrayList<>();
            callbacks.add(callback);
            callbacksMap.put(serviceId, callbacks);
        }
    }
}

private static boolean hasBeenCalled(int serviceId) {
    return calledServices.contains(serviceId);
}

interface Callback {
    void onPreExecute();

    void onPostExecute(Object object);
}

static class ServiceAsyncTask extends AsyncTask<Object, Object, Object> {
    private final int serviceId;
    private final Callback mCallback;

    ServiceAsyncTask(int serviceId, Callback callback) {
        this.serviceId = serviceId;
        this.mCallback = callback;
    }

    @Override
    protected void onPreExecute() {
        mCallback.onPreExecute();
    }

    Object doInBackground(Object... params) {
        return WebService.call(serviceId);
    }

    @Override
    protected void onPostExecute(Object o) {
        mCallback.onPostExecute(o);

         if (!callbacksMap.containsKey(serviceId)) return;

        for (Callback callback : callbacksMap.get(serviceId)) {
            callback.onPostExecute(o);
        }

        callbacksMap.remove(serviceId);
        calledServices.remove(serviceId);
    }
}

}

我希望你能帮助我,并为我可能做过的任何拼写错误或语法错误道歉。

3 个答案:

答案 0 :(得分:0)

当前片段可见时进行API调用。

例如,

  private boolean hasLoadedOnce= false; 
  @Override
  public void setUserVisibleHint(boolean isFragmentVisible) {
     super.setUserVisibleHint(true);
     if (this.isVisible()) {
         // we check that the fragment is becoming visible
        if (isFragmentVisible && !hasLoadedOnce) {
            new ServiceAsyncTask().execute();
            hasLoadedOnce = true;
        }
     }
  }

我希望,通过这种方式,你可以在内部管理api调用并轻松更新。

答案 1 :(得分:0)

我有类似你的问题。我还有一个回调,它由想要使用数据的每个视图/片段实现。然后我有一个asynctask加载数据。当我得到响应时,我将对象保存到一个管理器类中,该类包括我必须通知视图更新的回调列表。因此,实现回调的所有视图/片段都必须自己在管理器上注册。

代码示例: Example

答案 2 :(得分:0)

您可以在Java(1.5或更高版本)中使用枚举,如下所示:-

enum Tasks {
   task1, task2
}

并在这样的接口方法中传递'Tasks'类型的参数:-

interface Callback {
  void onPreExecute(Tasks task);

  void onPostExecute(Tasks task, Object object);
}

并像这样使用它:-

callback.onPreExecute(Tasks.task1); or callback.onPostExecute(Tasks.task1, object);