一个 AsynckTask 的多个回调

Posted

技术标签:

【中文标题】一个 AsynckTask 的多个回调【英文标题】:Multiple callbacks for one AsynckTask 【发布时间】:2017-06-20 14:06:21 【问题描述】:

我正在编写一个应用程序,其中我在 ViewPager 中有不同的片段。在每个片段中,我使用几个 AsyncTask 从 Web 服务器获取数据。一些片段需要调用相同的 AsynTask(service),但如果其中一个已经调用它,因为服务需要一段时间才能响应,我想防止再次调用它,而是让 AsyncTask 发送结果到所有调用它的片段。当用户更新片段(即SwipeToRefresh)时,我还需要更新所有片段中的数据。我今天使用的方法是一个函数,我验证服务是否已被调用,如果不是,则保存一个标志以指示该服务已被调用,并使用接收回调接口的 AsyncTask 调用服务以发送结果到请求的 Fragmnet,如果在另一方面,服务已经被调用,则将 Callback 添加到 Callback 列表中,稍后在 AsyncTask.onPostExecute 中遍历该列表以将结果发送到所有 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);
    

我希望你能帮助我,对于我可能犯的任何拼写错误或语法错误,我深表歉意。

【问题讨论】:

【参考方案1】:

在当前片段可见时进行 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;
        
     
  

我希望,这样你就可以在fragment内部管理api调用并轻松更新。

【讨论】:

【参考方案2】:

我也遇到了和你一样的问题。我还有一个回调,它由想要使用数据的每个视图/片段实现。然后我有一个加载数据的异步任务。当我收到响应时,我将对象保存到一个管理器类中,其中包括我必须通知以进行视图更新的回调列表。所以所有实现回调的视图/片段都必须自己在管理器上注册。

代码示例: Example

【讨论】:

【参考方案3】:

您可以像这样在 java(1.5 或更高版本)中使用枚举:-

enum Tasks 
   task1, task2

并在您的接口方法中传递“任务”类型的参数,如下所示:-

interface Callback 
  void onPreExecute(Tasks task);

  void onPostExecute(Tasks task, Object object);

并像这样使用它:-

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

【讨论】:

以上是关于一个 AsynckTask 的多个回调的主要内容,如果未能解决你的问题,请参考以下文章

我可以在破折号情节回调中使用多个输入,但只有一个触发回调吗?

一个通知的多个回调 Pushsharp

等待解决多个回调

flutter 同时执行多个异步请求回调

如何为 Autodesk Forge App 指定多个回调 URL?

如何在 jpicker 中使用多个回调