2010-07-28 54 views
1

我試圖找出正確的方法來創建一個AsyncTask從互聯網檢索一些數據,然後該數據並將其捆綁在一個Intent中並將其傳遞給一個新的活動(一個列表顯示)。所以在第一個活動中我只有一個EditText和Button。在OnClick的情況下,任務應該被調用,並且當它完成時,數據應該被捆綁在一個Intent中並傳遞給下一個Activity。問題是,當我從onPostExecute獲取結果並將它們設置爲主活動的實例變量時,該任務完成時該實例變量仍然爲空。這裏是代碼的準系統版本:未在AsyncTask的onPostExecute中設置Activity的實例變量,或者如何將數據從AsyncTask返回到主UI線程

public class SearchActivity extends Activity implements OnClickListener 
{ 
    static final String TAG = "SearchActivity"; 
    private EditText searchInput; 
    private Button searchBtn; 
    private PlacesList places; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.search_activity); 

     searchBtn = (Button) findViewById(R.id.button_search); 
     searchInput = (EditText) findViewById(R.id.search_input); 

     searchBtn.setOnClickListener(this); 
    } 

    public void onClick(View v) { 
     if(v == searchBtn) 
     { 
      String input = searchInput.getText().toString(); 
      if(input != null && input.length() != 0) 
      { 

       try { 
        new TestTask().execute(input); 
        Bundle bundle = new Bundle(); 
        bundle.putParcelable("places", places); 
        Intent i = new Intent(this, SearchResultsActivity.class); 
        i.putExtras(bundle); 

        startActivity(i); 
       } catch(Exception ex) { 
        ex.printStackTrace(); 
       } 
      } 
     } 
    } 

    private class TestTask extends AsyncTask<String, Void, PlacesList> 
    { 
     private ProgressDialog dlg = new ProgressDialog(SearchActivity.this); 

     @Override 
     protected void onPreExecute() 
     { 
      dlg.setMessage("test"); 
      dlg.show(); 
     } 

     @Override 
     protected PlacesList doInBackground(String...args) 
     { 
      try 
      { 
       return new PlaceLocator().retrieveResults(args[0]); 
      } 
      catch (Exception e) 
      { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      return new PlacesList(); 
     } 

     @Override 
     protected void onPostExecute(PlacesList results) 
     { 
      SearchActivity.this.places = results; 
      if(dlg.isShowing()) 
       dlg.dismiss(); 
     } 
    } 
} 

當我調試我看到onPostExecute確實包含一個有效的PlacesList全部結果的應用程序,所以爲什麼實例變量的地方設置爲空執行任務後?我正在從錯誤地從AsyncTask「返回數據」?

回答

4

根據定義,AsyncTask在不同的線程中執行。因此,在調用execute之後,您無法期望結果立即可用。相反,你應該觸發新的意圖關閉的AsyncTask完成的:

public void onClick(View v) { 
     if(v == searchBtn) 
     { 
      String input = searchInput.getText().toString(); 
      if(input != null && input.length() != 0) 
      { 

       try { 
        new TestTask().execute(input); 

       } catch(Exception ex) { 
        ex.printStackTrace(); 
       } 
      } 
     } 
    } 

private void startSearch(PlaceList places) { 
    Bundle bundle = new Bundle(); 
    bundle.putParcelable("places", places); 
    Intent i = new Intent(this, SearchResultsActivity.class); 
    i.putExtras(bundle); 

    startActivity(i); 
} 

private class TestTask extends AsyncTask<String, Void, PlacesList> 
{ 
... 

     @Override 
     protected void onPostExecute(PlacesList results) 
     { 
      startSearch(results); 
      if(dlg.isShowing()) 
       dlg.dismiss(); 
     } 

} 
+0

感謝您的解釋,這很好。 – 2010-07-29 19:05:41

+0

'startSearch'是否必須聲明爲靜態? – 2011-02-13 16:49:58

+0

@Eugene van der Merwe:不,TestTask是一個內部類,所以它可以訪問其父類中的所有方法和變量。如果我已經將TestTask聲明爲一個靜態內部類,那麼是的,startSearch需要靜態TestTask來訪問它。有關區別的更多信息,請參閱http://download.oracle.com/javase/tutorial/java/javaOO/nested.html – 2011-02-14 17:58:32

0

我打這個線程,而尋找一個答案我終於在這裏找到:Common class for AsyncTask in Android?

這是一個非常優雅的和通用的解決方案這個問題。

PS。請記住,即使AsyncTasks在不同的線程上執行,onPostExecute也會在UI線程上完成,從而允許與UI直接通信。

相關問題