2017-02-03 1 views
2

저는 ViewPager에 다른 프래그먼트가있는 어플리케이션을 작성하고 있습니다. 각 조각에서 나는 웹 서버로부터 데이터를 가져 오는 데 몇 개의 AsyncTask를 사용한다. 조각 중 일부는 동일한 AsynTask (서비스)를 호출해야하지만, 그 중 하나가 이미 호출 한 경우 서비스가 응답하는 데 시간이 걸리므로 호출하지 못하게하려고합니다. 대신 AsyncTask에서 그것을 불렀던 모든 조각들에게 결과. 또한 사용자가 조각 (SwipeToRefresh)을 업데이트 할 때 모든 조각에서 데이터를 업데이트해야합니다. 내가 오늘 가지고있는 aproach 함수는 호출 된 서비스가 유효한지 확인하는 함수이며, 그렇지 않은 경우 서비스가 호출되었음을 나타내는 플래그를 저장하고 AsyncTask를 사용하여 호출하는 콜백 인터페이스를 사용하는 서비스를 호출합니다. 결과를 요청하는 Fragmnet으로 보내고 다른 방법으로 서비스가 이미 호출 된 경우 Callback 목록에 콜백을 추가합니다. 콜백 목록은 나중에 AsyncTask.onPostExecute에서 통과하여 모든 가상 네트워크에 다시 전달합니다.하나의 AsynckTask에 대한 다중 콜백

가장 큰 문제는 사용자가 잠시 후 앱을 열 때와 같이 메모리 누수가 발생하고 (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); 
    } 
} 

} 난 당신이 날 도울 수 있기를 바랍니다

나는 오타에 대해 사과 나 문법 오류가 내가있을 수 있습니다 끝난.

답변

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; 
     } 
    } 
    } 

I 희망, 당신의 fragment 내부 API 호출을 mangage 쉽게 업데이트 할 수 있습니다 이런 식으로.

0

EventBus 라이브러리를 사용하는 것이 좋습니다. 모든 조각으로 이벤트에 가입하십시오. 한 번 작업을 호출하고 결과를 얻을 때 이벤트를 게시하십시오.

0

나는 비슷한 문제가있었습니다. 나는 또한 데이터를 사용하고자하는 모든 뷰/프래그먼트에 의해 구현되는 콜백을 가지고있다. 그런 다음 데이터를로드하는 asynctask가 있습니다. 응답을 받으면 뷰 업데이트를 알리는 콜백 목록을 포함하는 관리자 클래스에 개체를 저장합니다. 따라서 콜백을 구현하는 모든 뷰/조각은 관리자가 스스로 등록해야합니다.

코드 예 : Example

관련 문제