2016-05-17 83 views
-1

我已經實現了一種將結果從onPostExecute返回到我的主要活動的方法。我想知道這是否是我做的正確的事情,是否還有改進的機會,如果這不是最好的方法,那麼最好的方法是什麼?從AsyncTask獲取結果給調用者類的最佳方法

這是我做了什麼:

public class MainClass implements AsyncResponse { 
    private MyAsyncTask asyncTask; 

    public MainClass() { 
     asyncTask = new MyAsyncTask(); 
     asyncTask.asyncResponse = this; 
    } 

    public void startTask({ 
     asyncTask.execute("string"); 
    } 

    @Override 
    public void processDone(String res) { 
     // got response in MainClass from onPostExecute 
    } 

    private class MyAsyncTask extends AsyncTask<String, String, String> { 

     protected AsyncResponse asyncResponse = null; 

     @Override 
     protected String doInBackground(String... urls) { 
      return "some processed string"; 
     } 

     @Override 
     protected void onPostExecute(String res) { 
      this.asyncResponse.processDone(res); 
     } 
    } 
} 

這裏的AsyncResponse接口:

public interface AsyncResponse { 
    void processDone(String res); 
} 

我想在處理速度方面,一個普通的Android移動設備上,這會不會知道一個好方法,如果不是,我該如何改進它,使其成爲一個好方法?

感謝。

回答

0

我總是這樣做,從來沒有任何問題。我會說這是最好的方法。

0
在一行

沒有任何回調

String s= new MyAsyncTask().execute().get(); 
0

您添加了不必要的接口 - 也許它使你的代碼少使用。

首先,如果您創建AsyncTask作爲您的Activity中的類,則不需要該接口。你可以簡單地這樣做:

@Override 
protected void onPostExecute(String res) { 
    processDone(res); 
} 

AsyncTask將執行UI線程onPostExecute,你可以調用沒有接口Activity方法。第二,如果你在類Activity之外創建AsyncTask(例如,在它自己的java文件中),那麼你可以使用這種方法,但它不是一個好主意,因爲它會在另一個線程上保留對Activity的引用 - 這是內存泄漏風險。

爲了避免這種情況,您的界面應該在一個單獨的類中實現,如傳遞到AsyncTask類的AsyncTaskResponse.java

最後,AsyncTaskString的形式提供響應(如果足夠的話)。你應該看看文檔上AsyncTask

https://developer.android.com/reference/android/os/AsyncTask.html

+0

但我可以通過分離asynctask類並在其他類中使用它來重新使用它。那我必須有一個界面對嗎? –

0

你是包裝內的另一個POJO類AsyncTask;這樣做不會傷害,但幾乎沒有什麼好處。

請考慮當任務完成後,您需要在某處回撥通知。您的MainClass將在processDone()中得到回覆,但需要收聽MainClass以獲取該通知。

這個模式我總是用我的AsyncTask子類:

public class GetDataRemoteTask extends AsyncTask<String, Void, Data> { 

    private static final String TAG = "GetDataRemoteTask "; 

    private WeakReference<GetDataResultListener> mListenerRef; 

    private Exception mExc; 

    @Override 
    protected Data doInBackground(String... params) { 

     Data result = null; 

     try { 
      result = mService.getData(params[0], params[1], params[2]); 

     } catch (Exception e) { 
      Log.e(TAG, "Error occurred getting data", e); 
      mExc = e; 
     } 
     return result; 
    } 

    @Override 
    protected void onPostExecute(Data result) { 

     if (mListenerRef != null) { 
      GetDataResultListener listener = mListenerRef.get(); 
      if (listener != null) { 
       if (mExc == null) { 
        listener.dataReceived(result); 
       } else { 
        listener.dataException(mExc); 
       } 
      } 
     } 
    } 

    public void setGetDataResultListener(GetDataResultListener listener) { 

     if (listener == null) { 
      this.mListenerRef = null; 
     } else { 
      this.mListenerRef = new WeakReference<GetDataResultListener >(listener); 
     } 
    } 

    public static interface GetDataResultListener { 

     public void dataReceived(Data data); 

     public void dataException(Exception exc); 
    } 

} 

所以要開始,在這裏我有一個接口,像你一樣,用於連接到AsyncTask。但是我並沒有用我的AsyncTask實現,我期望我將有一個ActivityFragment來實現這個接口。 (這就是爲什麼我使用WeakReference;如果Activity完成,我的AsyncTask將不會保持到Activity。但這也意味着我不能使用匿名類偵聽器,除非客戶端持有該引用。)

我的客戶端代碼如下所示:

 GetDataRemoteTask task = new GetDataRemoteTask(); 
     task.setListener(this); 
     task.execute(param1, param2, param3); 

我也有辦法找出是否有發生在後臺任務異常。任何後臺異常應始終報告給客戶端,客戶端可以決定如何最好地處理異常 - 例如爲用戶彈出對話框,以便他們知道請求失敗。

我認爲AsyncTask的一大缺點是它沒有更多的結構來處理後臺線程中發生的異常。

我的任務保存對異常的引用,但我也使用Pair<Data, Exception>作爲返回結果的類型參數,所以我不需要異常屬性。

使用此模式幫助我避免了編碼AsyncTask子類時發生的一些典型問題。

相關問題