Activity instance variable not set to onPostExecute AsyncTask or how to return data from AsyncTask to main UI thread

I am trying to figure out the correct way to create AsyncTask to extract some data from the Internet, and then take this data and lay it out in intention and pass it to a new action (list display). Therefore, in the first action, I have only EditText and Button. In the case of OnClick, the task must be called, and when it is completed, the data must be combined inside the Intent and passed to the next action. The problem is that when I take the results of onPostExecute and set them to the instance variable of the main action, this instance variable is still null when the task is completed. Below is the basic version of the code:

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(); } } } 

When I debug the application that I see, onPostExecute really contains a valid PlacesList full of results, so why, after the task is complete, are the instance variable locations set to zero? Am I "returning data" incorrectly from AsyncTask?

+1
source share
2 answers

AsyncTask, by definition, runs in a different thread. Thus, you cannot expect the results to be immediately available after the execute call. Instead, you should activate the new concept after AsyncTask completes:

 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(); } } 
+4
source

I got into this thread looking for the answer that I eventually found here: Generic class for AsyncTask in Android?

This is a truly elegant and general solution to this problem.

PS. Keep in mind that although AsyncTasks is running on a different thread, onPostExecute is running on the user interface thread, which allows you to directly communicate with the user interface.

0
source

All Articles