2013-03-25 4 views
7

안녕하세요.여러 AsyncTasks에서 결과 얻기

나는 AsyncTask을 호출하여 네트워크에서 일부 데이터를 가져 오는 method이 있습니다.

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

+0

RemoteView를 생성자의 AsyncTask UpdateTaskPrice에 전달하고 onPostExecute 내부의 setTextViewText를 전달하지 않는 이유는 무엇입니까? 이런 방식으로 각 AsyncTask는 업데이트 할 뷰를 알고 있으므로 –

+0

인텐시브 서비스를 사용할 필요조차 없습니다. 그것은 충분히 동기식입니다. – njzk2

답변

10

AsyncTask는 비동기 적이며 별도의 스레드에서 실행됩니다. 따라서 AsyncTask를 실행 한 후에 바로 다음 문장에서 AsyncTask의 결과를 얻을 수 없습니다.

AsyncTask의 상대 결과를 얻으려면 UpdateTaskPrice 클래스에 멤버 변수 "mRequestId"를 추가하고 UpdateTaskPrice.execute를 호출하기 전에 고유 요청 ID를 설정하십시오. UpdateTaskPrice 클래스의 "onPostExecute"메소드에있는

의 경우이 요청 ID를 사용하여 결과를 반환하고 처리 할 수 ​​있습니다.

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' 메소드에 어떻게 전달할 수 있는지 잘 모르니까 좀 더 정교하게 답할 수 있는지 물어보십시오. 다시 한 번 감사드립니다! –

+1

AsyncTasks는 백그라운드에서 실행됩니다. getPrice 메소드가 반환 한 결과를 표시하려면 Activity 뷰를 업데이트해야합니다. onPostExecute 메서드는 Activity의 주 스레드에서 실행됩니다. UpdateTaskPrice에서 활동 참조를 전달하면 (mRequestId와 동일) onPostExecute 메소드에서 Activity 뷰에 액세스 할 수 있습니다. 결과를 구문 분석하고 결과에서 파싱 된 가격을 보여주는 책임 활동의 다른 메소드를 호출 할 수도 있습니다. – Amit

+0

감사합니다. 나는 그것을 얻었고 그것을 얻지 못했습니다 ... 제발 Amit에게 코드를 어떻게 수정해야하는지 친절하게 보여 주시겠습니까? 감사! –

0

글쎄, 난 당신이 AsyncTask의 생성자에서 고유 요청 ID를 전달할 수 있다고 생각합니다. 그런 다음 postExecute() 방법, 결과와 UI 및 고유 요청 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와 수 없습니다, 당신 이 문제를 구조화하기 위해 더 많은 캡슐화를 사용해야합니다.

당신의 구조에 문제가 ...

당신이 처음 task.execute (기호) 후 복귀가 문을 실행할 새로운 스레드를 시작
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; 
} 

; 귀하의 경우

들으은 여러 AsycTask에서 데이터를 검색하는 데 사용할 수있는 패턴이다 ... .. 포스트 뭐하는 .. 그것은 반환 문이며, 그것은 사전 exucute합니다

//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; 
    } 
} 

도움이되기를 바랍니다.