2013-08-21 3 views
5

Android 용 애플리케이션에서 AsyncTask를 반복 할 가능성이 있는지 의심 스럽습니다. 몇 가지 작업을 반복하고 싶습니다. 예를 들어 서버에서 파일을 다운로드하는 경우, n 번은 파일을 다운로드 할 수없는 경우 n 번 시도하는 것입니다. 이 작업을 수행하는 빠른 방법이 있습니까?Repeat AsyncTask

+1

정확히 무엇이 문제입니까? 실패한 경우 동일한 AsyncTask를 다시 시작할 수 있습니다. –

+0

비동기 작업 반복을위한 서비스 및 alaram 관리자 클래스 사용 – Mohit

답변

8

AsyncTask 을 반복 할 수는 없지만 실행하는 작업을 반복 할 수있는을 반복 할 수 있습니다.

AsyncTask 대신 확장 할 수있는이 작은 도우미 클래스를 만들었습니다. 유일하게 큰 차이점은 doInBackground 대신 repeatInBackground를 사용하고 onPostExecute는 새로운 매개 변수 인 최종 예외가 발생한다는 것입니다.

결과가 null과 다를 때까지 repeatInBackground 내의 모든 항목이 자동으로 반복됩니다. 예외가 throw되지 않고 maxTries보다 작습니다.

루프 내에서 마지막으로 throw 된 예외는 onPostExecute (Result, Exception)에 반환됩니다.

RepeatableAsyncTask (int retries) 생성자를 사용하여 최대 시도를 설정할 수 있습니다.

public abstract class RepeatableAsyncTask<A, B, C> extends AsyncTask<A, B, C> { 
    private static final String TAG = "RepeatableAsyncTask"; 
    public static final int DEFAULT_MAX_RETRY = 5; 

    private int mMaxRetries = DEFAULT_MAX_RETRY; 
    private Exception mException = null; 

    /** 
    * Default constructor 
    */ 
    public RepeatableAsyncTask() { 
     super(); 
    } 

    /** 
    * Constructs an AsyncTask that will repeate itself for max Retries 
    * @param retries Max Retries. 
    */ 
    public RepeatableAsyncTask(int retries) { 
     super(); 
     mMaxRetries = retries; 
    } 

    /** 
    * Will be repeated for max retries while the result is null or an exception is thrown. 
    * @param inputs Same as AsyncTask's 
    * @return Same as AsyncTask's 
    */ 
    protected abstract C repeatInBackground(A...inputs); 

    @Override 
    protected final C doInBackground(A...inputs) { 
     int tries = 0; 
     C result = null; 

     /* This is the main loop, repeatInBackground will be repeated until result will not be null */ 
     while(tries++ < mMaxRetries && result == null) { 
      try { 
       result = repeatInBackground(inputs); 
      } catch (Exception exception) { 
       /* You might want to log the exception everytime, do it here. */ 
       mException = exception; 
      } 
     } 
     return result; 
    } 

    /** 
    * Like onPostExecute but will return an eventual Exception 
    * @param c Result same as AsyncTask 
    * @param exception Exception thrown in the loop, even if the result is not null. 
    */ 
    protected abstract void onPostExecute(C c, Exception exception); 

    @Override 
    protected final void onPostExecute(C c) { 
     super.onPostExecute(c); 
     onPostExecute(c, mException); 
    } 
} 
+0

이 작업은 정적 클래스로 작동합니까? 오리엔테이션 변경 중에 매달려있는 참조를 피하기 위해 정적 인 AsyncTasks를 사용하고 싶습니다. 수업이 정적으로 작동하는지 알고 있습니까? –

+0

난 항상 정적으로 사용. –

1
당신은 동일한 AsyncTask 객체 according to the AsyncTask Docs

작업이 (제 2 실행 시도하면, 예외가 발생한다.)

한번만 실행될 수를 재사용 할 수

그러나 루프 내부에서 필요한 클래스의 많은 새로운 객체를 만들 수 있습니다. 그러나 doInBackground() 안에 n 번 다운로드 작업을하는 것이 더 좋습니다.

이 다음 질문에 대답 문제

0

내가했던 그 방법에 관해서는 구체적하시기 바랍니다하지 않습니다. try (시도 == MAX_RETRY) 또는 결과가 널 (NULL)이 아닐 때까지 시도하고 시도 할 수 있습니다. 수락 된 답변에서 약간 수정 된 코드를 사용하면 더 좋습니다.

private class RssReaderTask extends AsyncTask<String, Void, ArrayList<RssItem>> { 

    // max number of tries when something is wrong 
    private static final int MAX_RETRY = 3; 

    @Override 
    protected ArrayList<RssItem> doInBackground(String... params) { 

     ArrayList<RssItem> result = null; 
     int tries = 0; 

     while(tries++ < MAX_RETRY && result == null) { 
      try { 
       Log.i("RssReaderTask", "********** doInBackground: Processing... Trial: " + tries); 
       URL url = new URL(params[0]); 
       RssFeed feed = RssReader.read(url); 
       result = feed.getRssItems(); 
      } catch (Exception ex) { 
       Log.i("RssReaderTask", "********** doInBackground: Feed error!"); 
      } 
     } 

     return result; 
    } 

    @Override 
    protected void onPostExecute(ArrayList<RssItem> result) { 
     // deal with result 
    } 

}