2013-03-25 48 views
7

嗨,感謝您的幫助。從幾個AsyncTasks中獲取結果

我有一個method調用AsyncTask來從網絡中檢索一些數據。

method被依次調用幾次,因此啓動了幾個AsyncTasks

method的每次啓動中,我需要從相關的AsyncTask(而不是從其他在之前或之後調用的其他AsyncTask)中獲取正確的結果。

非常感謝任何幫助。


編輯編輯編輯編輯 添加了其餘的代碼。

請注意:整個過程運行在服務內。

public static class UpdateService extends Service { 
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 

     int[] appWidgetIds = intent.getIntArrayExtra("widgetsids"); 
     final int N = appWidgetIds.length; 
     AppWidgetManager manager = AppWidgetManager.getInstance(this); 
     for (int i = 0; i < N; i++) { 
      int appWidgetId = appWidgetIds[i]; 
      Log.e("","i="+Integer.toString(i)+ " di "+Integer.toString(N)); 
      RemoteViews view = buildUpdate(getApplicationContext(), 
        appWidgetIds); 
      manager.updateAppWidget(appWidgetId, view); 
     } 
     return (START_NOT_STICKY); 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return null; 
    } 
} 

private static RemoteViews buildUpdate(Context ctxt, int[] appWidgetIds) { 
    RemoteViews updateViews = new RemoteViews(ctxt.getPackageName(), 
      R.layout.widget); 
     updateViews.setTextViewText(R.id.price1, getPrice(list.get(0) 
      .getSymbol())); 

}   
    //THIS METHOD IS CALLED SEVERAL TIMES IN SEQUENCE <---- 
    private static String getPrice(String symbol) { 
    String result=""; 
    UpdateTaskPrice up = new UpdateTaskPrice(); 
    up.execute(symbol, null, null); 
    //HERE I WANT THE RESULT FROM onPostExecute() <---- 
    return result; 
} 

//THIS IS THE ASYNCTASK WHICH IS LAUNCHED SEVERAL TIMES 
public class UpdateTaskPrice extends AsyncTask<String, Void, String> { 

    @Override 
    protected void onProgressUpdate(Void... progress) { 
    } 

    @Override 
    protected void onPostExecute(String result) { 
    //HERE I RECEIVE THE RESULT FROM doInBackground <---- 
    //I NEED TO PASS IT BACK TO getPrice() <---- 
    } 

    @Override 
    protected String doInBackground(String... symbol) { 
     String result = ""; 
     DefaultHttpClient client = new DefaultHttpClient(); 
     String srt = ""; 

     String url = context.getString(R.string.urlaternativo).concat(
       symbol[0]); 

     HttpGet getMethod = new HttpGet(url); 
     try { 
      ResponseHandler<String> responseHandler = new BasicResponseHandler(); 
      srt = client.execute(getMethod, responseHandler); 
      int inizio = srt.indexOf("<last data=\""); 
      int fine = srt.indexOf("\"/>", inizio + 12); 
      result = srt.substring(inizio + 12, fine); 

     } catch (Throwable t) { 
      // Log.e("ERROR", "ERROR", t); 
     } 
     //HERE I GET THE RESULT I WANT, AND PASS IT TO onPostExecute() <---- 
     return result; 
    } 
} 
+1

這是可行的,但不推薦通過'Asynctask.get()',我已經在[這個答案]中解釋了這個特殊的API多一點(http://stackoverflow.com/questions/8921244/return-data-from -asynctask-的Android/8922074#8922074)。 – yorkw 2013-03-27 22:09:37

+0

爲什麼不直接將RemoteViews傳遞給其構造函數中的AsyncTask UpdateTaskPrice以及onPostExecute內部的'setTextViewText'?通過這種方式,每個AsyncTask知道要更新哪個視圖,並且甚至不需要結果 – 2013-04-02 08:30:10

+0

就可以使用intentservice。這足夠同步。 – njzk2 2013-04-02 17:01:44

回答

10

AsyncTask是異步的並且在單獨的線程中運行。所以在執行它之後,在下一個語句中不可能得到AsyncTask的結果。

要從AsyncTask獲得相關結果,請在UpdateTaskPrice類中添加成員變量「mRequestId」,並在調用UpdateTaskPrice.execute之前設置唯一的請求ID。

在UpdateTaskPrice類的「onPostExecute」方法中,可以使用此請求標識返回並處理結果。

public class UpdateTaskPrice extends AsyncTask<String, Void, String> { 

    protected int mRequestId; 

    public void setRequestId (int requestId) 
    { 
     this.mRequestId = requestId; 
    } 

    @Override 
    protected void onProgressUpdate(Void... progress) { 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     // do whatever with result using mRequestId 
    } 

    @Override 
    protected String doInBackground(String... symbol) { 
     String result = ""; 
     DefaultHttpClient client = new DefaultHttpClient(); 
     String srt = ""; 

     String url = context.getString(R.string.urlaternativo).concat(
       symbol[0]); 

     HttpGet getMethod = new HttpGet(url); 
     try { 
      ResponseHandler<String> responseHandler = new BasicResponseHandler(); 
      srt = client.execute(getMethod, responseHandler); 
      int inizio = srt.indexOf("<last data=\""); 
      int fine = srt.indexOf("\"/>", inizio + 12); 
      result = srt.substring(inizio + 12, fine); 

     } catch (Throwable t) { 
      // Log.e("ERROR", "ERROR", t); 
     } 
     //HERE I GET THE RESULT I WANT, AND PASS IT TO onPostExecute() <---- 
     return result; 
    } 
} 
+0

非常感謝!我懷疑我必須這樣做。請我問你是否可以詳細說明答案,因爲我不太清楚如何將結果和requestId傳遞給'getPrice'方法。再次感謝! – 2013-03-25 14:00:26

+1

AsyncTasks旨在在後臺運行。爲了顯示getPrice方法返回的結果,您需要更新您的Activity的視圖。 onPostExecute方法在Activity的主線程中運行。如果您在UpdateTaskPrice中傳遞活動的引用(與mRequestId相同),則可以在onPostExecute方法中訪問Activity的視圖。您也可以調用您的活動的另一種方法負責解析結果並顯示從結果解析的價格 – Amit 2013-03-25 14:09:49

+0

謝謝。我明白了,但是我不明白...請阿米特如此友善地告訴我該如何修改代碼?謝謝! – 2013-03-25 15:11:05

0

那麼,我認爲你可以在AsyncTask的構造函數中傳遞唯一的請求id。然後在postExecute()方法,更新結果的用戶界面和獨特的請求ID -

public class UpdateTaskPrice extends AsyncTask<String, Void, String> { 

    private int mIdentifier; 
    private Service mService; 

    public UpdateTaskPrice(Service service, int identifier) { 
     this.mIdentifier = identifier; 
    } 

    @Override 
    protected void onProgressUpdate(Void... progress) { 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     ((UpdateService) mService).informPrice(mIdentifier, result); 
    } 

    @Override 
    protected String doInBackground(String... symbol) { 
     String result = ""; 
     DefaultHttpClient client = new DefaultHttpClient(); 
     String srt = ""; 

     String url = context.getString(R.string.urlaternativo).concat(
       symbol[0]); 

     HttpGet getMethod = new HttpGet(url); 
     try { 
      ResponseHandler<String> responseHandler = new BasicResponseHandler(); 
      srt = client.execute(getMethod, responseHandler); 
      int inizio = srt.indexOf("<last data=\""); 
      int fine = srt.indexOf("\"/>", inizio + 12); 
      result = srt.substring(inizio + 12, fine); 

     } catch (Throwable t) { 
      // Log.e("ERROR", "ERROR", t); 
     } 
     //HERE I GET THE RESULT I WANT, AND PASS IT TO onPostExecute() <---- 
     return result; 
    } 
} 
0

您可以從多個的AsyncTask的數據,但你想要的結果的地方是不可能 與asyctask,你需要使用更多的封裝來解決這個問題。

與結構問題是...

private static String getPrice(String symbol) { 
    String result=""; 
    UpdateTaskPrice up = new UpdateTaskPrice(); 
    up.execute(symbol, null, null); 
    //HERE I WANT THE RESULT FROM onPostExecute() <---- 
    return result; 
} 

當你開始新的線程將首先執行是task.execute(符號)後返回的聲明;你的情況是return語句,然後它會exucute預.. ..幹什麼,後...

聽到的是,你可以用它來從多個AsycTask檢索數據的模式

//Calling to the method callAsyncTask; 
callAsyncTask(new AsyncResultCallback(){ 
    public void onResult(String result, String symbol){ 
     //TODO dosomthing with the result 
    } 
}); 


public void callAsyncTask(AsyncResultCallback callback){ 
    new UpdateTaskPrice(callback).execurte(symbol); 
} 

public interface AsyncResultCallback{ 
    public void onResult(String result, String symbol); 
} 

public class UpdateTaskPrice extends AsyncTask<String, Void, String> { 

    AsyncResultCallback callback; 
    String symbol; 

    UpdateTaskPrice(AsyncResultCallback callback){ 
     this.callback = callback; 
    } 

    @Override 
    protected void onProgressUpdate(Void... progress) { 
    } 

    @Override 
    protected void onPostExecute(String result) { 
     callback.onResult(result, symbol); 
    } 

    @Override 
    protected String doInBackground(String... symbol) { 
     this.symbol = symbol; 
     String result = ""; 
     DefaultHttpClient client = new DefaultHttpClient(); 
     String srt = ""; 

     String url = context.getString(R.string.urlaternativo).concat(symbol[0]); 

     HttpGet getMethod = new HttpGet(url); 
     try { 
      ResponseHandler<String> responseHandler = new BasicResponseHandler(); 
      srt = client.execute(getMethod, responseHandler); 
      int inizio = srt.indexOf("<last data=\""); 
      int fine = srt.indexOf("\"/>", inizio + 12); 
      result = srt.substring(inizio + 12, fine); 

     } catch (Throwable t) { 
      // Log.e("ERROR", "ERROR", t); 
     } 
      //HERE I GET THE RESULT I WANT, AND PASS IT TO onPostExecute() <---- 
     return result; 
    } 
} 

希望有所幫助。