Переменная экземпляра Activity не устанавливается в onPostExecute AsyncTask или как вернуть данные из AsyncTask в основной поток пользовательского интерфейса - PullRequest
1 голос
/ 28 июля 2010

Я пытаюсь найти правильный способ создания AsyncTask для извлечения некоторых данных из Интернета, а затем для того, чтобы взять эти данные и связать их в Intent и передать их новому действию (отображение списка).Итак, в первом упражнении у меня просто есть EditText и Button.В случае OnClick должна быть вызвана задача, и когда она будет завершена, данные должны быть объединены в Intent и переданы следующему Activity.Проблема заключается в том, что когда я беру результаты из onPostExecute и устанавливаю их в качестве переменной экземпляра основного действия, эта переменная экземпляра все еще равна нулю, когда задача завершена.Вот базовая версия кода:

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?

Ответы [ 2 ]

4 голосов
/ 28 июля 2010

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 голосов
/ 23 сентября 2011

Я нажал эту тему, ища ответ, который в конце концов нашел здесь: Общий класс для AsyncTask в Android?

Это действительно элегантное и универсальное решение для этой проблемы.

PS.Имейте в виду, что хотя AsyncTasks выполняются в другом потоке, onPostExecute выполняется в потоке пользовательского интерфейса, обеспечивая прямую связь с пользовательским интерфейсом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...