2013-08-21 29 views
5

Tôi có nghi ngờ về khả năng lặp lại AsyncTask trong một ứng dụng cho Android. Tôi muốn lặp lại một số thao tác, việc tải xuống tệp từ máy chủ chẳng hạn, n lần nếu không thể vì một số lý do tải xuống tệp. Có một cách nhanh chóng để làm điều này?Lặp lại AsyncTask

+1

Vấn đề chính xác là gì? Bạn chỉ có thể khởi động lại AsyncTask tương tự nếu nó không thành công. –

+0

sử dụng dịch vụ và lớp quản lý alaram để lặp lại Async Task – Mohit

Trả lời

8

Bạn không thể lặp lại AsyncTask nhưng bạn có thể lặp lại các thao tác mà nó thực thi.

Tôi đã tạo lớp trợ giúp nhỏ này mà bạn có thể muốn mở rộng thay cho AsyncTask, khác biệt lớn duy nhất là bạn sẽ sử dụng repeatInBackground thay vì doInBackground và onPostExecute sẽ có tham số mới, ngoại lệ cuối cùng được ném.

Mọi thứ bên trong lặp lạiInBackground sẽ được lặp lại tự động cho đến khi kết quả khác với null/exception không được ném và có ít hơn maxTries.

Ngoại lệ cuối cùng được ném bên trong vòng lặp sẽ được trả về trong onPostExecute (Kết quả, Ngoại lệ).

Bạn có thể đặt các lần thử tối đa bằng cách sử dụng hàm tạo 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

Điều này có hoạt động như một lớp tĩnh không? Tôi thích sử dụng AsyncTask tĩnh để tránh tham chiếu lơ lửng trong khi thay đổi hướng. Bạn có biết lớp của bạn hoạt động tĩnh không? –

+0

Tôi luôn sử dụng nó tĩnh. –

1

Bạn không thể tái sử dụng cùng một đối tượng AsyncTask như, according to the AsyncTask Docs

Nhiệm vụ có thể được thực hiện chỉ một lần (một ngoại lệ sẽ được ném ra nếu một thi thứ hai là cố gắng.)

Nhưng bạn có thể tạo ra nhiều đối tượng mới của lớp bạn cần bên trong một vòng lặp. Tuy nhiên, bạn nên thực hiện thao tác tải xuống n số lần trong số doInBackground() của mình.

Nếu điều này không trả lời câu hỏi của bạn thì vui lòng cụ thể hơn về vấn đề của bạn

0

Tôi đã làm theo cách đó. Nó có thể thử và cố gắng cho đến khi (cố gắng == MAX_RETRY) hoặc kết quả là không null. Một mã được sửa đổi một chút từ câu trả lời được chấp nhận, tốt hơn cho tôi.

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 
    } 

}