不在AsyncTask的onPostExecute中设置Activity的实例变量或如何将数据从AsyncTask返回到主UI线程

我正在试图找出创建AsyncTask的正确方法,以便从互联网上检索一些数据,然后获取该数据并将其捆绑在Intent中并将其传递给新活动(列表显示)。 所以在第一个活动中我只有一个EditText和Button。 在OnClick的情况下,应该调用任务,当它完成时,数据应该捆绑在Intent中并传递给下一个Activity。 问题是当我从onPostExecute获取结果并将它们设置为主活动的实例变量时,该任务完成时该实例变量仍然为null。 这是代码的准系统版本:

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 { 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,那么为什么在执行任务后实例变量的位置设置为null? 我错误地从AsyncTask“返回数据”?

根据定义,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 { ... @Override protected void onPostExecute(PlacesList results) { startSearch(results); if(dlg.isShowing()) dlg.dismiss(); } } 

我在寻找我最终在这里找到的答案时遇到了这个问题: Android中AsyncTask的公共类?

对于这个问题,这是一个非常优雅和通用的解决方案。

PS。 请记住,即使在不同的线程上执行AsyncTasks,onPostExecute也会在UI线程上完成,从而允许与UI直接通信。