2013-03-25 3 views
7

Привет и спасибо за вашу помощь.Получение результатов от нескольких AsyncTasks

У меня есть method, который вызывает AsyncTask для извлечения некоторых данных из сети.

methodвызывается несколько раз подряд и поэтому запускает несколько AsyncTasks.

С каждого запуска method Мне нужно вернуть правильный результат из относительной AsyncTask (а не из какой-либо другой AsyncTask, которая была вызвана до или после).

Любая помощь очень ценится.


EDIT EDIT EDIT EDIT Добавлен остальной код.

Обращаем внимание, что:: весь процесс проходит внутри Служба.

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-андроид/8922074 # 8922074). – yorkw

+0

Почему вы просто не переносите RemoteViews в свою AsyncTask UpdateTaskPrice в свой конструктор и 'setTextViewText' внутри onPostExecute? Таким образом, каждый AsyncTask знает, какой вид обновить, и вам даже не понадобится результат –

+0

использовать intenservice. это достаточно синхронно. – njzk2

ответ

10

AsyncTask является асинхронным и запускается в отдельном потоке. Таким образом, невозможно получить результат AsyncTask в самом следующем операторе после его выполнения.

Чтобы получить относительные результаты от AsyncTask, добавьте переменную-член «mRequestId» в свой класс UpdateTaskPrice и перед вызовом UpdateTaskPrice.execute установите уникальный идентификатор запроса.

в методе «onPostExecute» вашего класса UpdateTaskPrice, вы можете возвращать и обрабатывать результат с помощью этого идентификатора запроса.

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

Спасибо большое! Я подозревал, что должен был сделать что-то подобное. Пожалуйста, любезно спрошу вас, можете ли вы дать более подробный ответ, потому что я не совсем уверен, как я могу передать результат и запрос на метод getPrice. Еще раз спасибо! –

+1

AsyncTasks предназначены для работы в фоновом режиме. Чтобы показать результаты, возвращаемые методом getPrice, вам необходимо обновить представление Activity. onPostExecute в главном потоке активности. Если вы передадите ссылку своей деятельности в UpdateTaskPrice (то же, что и mRequestId), вы можете получить доступ к представлению Activity в методе onPostExecute. Вы также можете вызвать другой метод своей деятельности, ответственный за анализ результата и показ цены, проанализированной из результата. – Amit

+0

Спасибо. Я получаю это, и я не понимаю ... Пожалуйста, Амит, ты был бы таким добрым, чтобы показать мне, как мне изменить код? Благодаря! –

0

Ну, я думаю, что вы можете передать уникальный идентификатор запроса в конструкторе AsyncTask. Затем в методе postExecute(), обновление пользовательского интерфейса с результатом и уникальный идентификатор запроса -

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 (символ); в вашем случае это оператор возврата, а затем он будет 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; 
    } 
} 

надеюсь, что помощь.

Смежные вопросы