2012-02-25 4 views
7

моя проблема такая же, как у этого Instance variable of Activity not being set in onPostExecute of AsyncTask or how to return data from AsyncTask to main UI thread , но я хочу отправить данные обратно на ту же самую деятельность вызова. Doesnt startActivity для намерений всегда перезапускает активностькак я могу отправить данные обратно из onPostExecute в AsyncTask?

ответ

13

На вариант заключается в использовании слушателей, где вы создаете интерфейс, ваши implents активности, что-то вроде:

public interface AsyncListener { 
    public void doStuff(MyObject obj); 
} 

Таким образом, если вы подклассов AsyncTask, легко добавить слушателя, то в onPostExecute(), вы могли бы сделать что-то вроде:

protected void onPostExecute(MyObject obj) { 
    asyncListener.doStuff(obj); 
} 
6

Это зависит от структуры вашего класса, но если ваш AsyncTask является классом в вашей деятельности, вы можете ссылаться на методы этой деятельности. Что вы могли бы сделать это в методе onPostExecute называют функцией вашей деятельности, которая проходит некоторые данные, которые были извлечены в AsyncTask к деятельности, где вы можете использовать его ..

код будет выглядеть следующим образом

class YourActivity extends Activity { 
    private static final int DIALOG_LOADING = 1; 

    public void onCreate(Bundle savedState) { 
    setContentView(R.layout.yourlayout); 
    showDialog(DIALOG_LOADING);  
    new LongRunningTask1().execute(1,2,3); 

    } 

    protected Dialog onCreateDialog(int dialogId) { 
    switch(dialogId) { 
     case DIALOG_LOADING: 
      ProgressDialog pDialog = new ProgressDialog(this); 
      pDialog.setTitle("Loading Data"); 
      pDialog.setMessage("Loading Data, please wait..."); 
      return pDialog; 
     default: 
      return super.onCreateDialog(dialogId); 
     }  
    } 

    private void onBackgroundTaskDataObtained(List<String> results) { 
     dismissDialog(DIALOG_LOADING); 
    //do stuff with the results here.. 
    } 

    private class LongRunningTask extends AsyncTask<Long, Integer, List<String>> { 
     @Override 
     protected void onPreExecute() { 
      //do pre execute stuff 
     } 

     @Override 
     protected List<String> doInBackground(Long... params) { 
      List<String> myData = new ArrayList<String>(); 
      for (int i = 0; i < params.length; i++) { 
       try { 
        Thread.sleep(params[i] * 1000); 
        myData.add("Some Data" + i); 
       } catch(InterruptedException ex) { 
       }     
      } 
      return myData; 
     } 

     @Override 
     protected void onPostExecute(List<String> result) { 
      YourActivity.this.onBackgroundTaskDataObtained(result); 
     }  
    } 

} 

Итак, типичный поток похож на этот, установите вид текущей страницы, а затем отобразите диалог выполнения. Сразу после этого запускается асинхронная задача (или всякий раз, когда это не имеет значения).

После завершения задачи async вызовите функцию активности и передайте ей данные. Не используйте общие данные в задаче async или вы рискуете проблемами с потоковой передачей. Вместо этого, как только вы закончите с этим, передайте ее активности. Если вы хотите, чтобы обновить представление постепенно делая работу, которую вы можете использовать на onProgressUpdate

+0

Спасибо за ваш ответ. Я не являюсь поклонником AsyncTask, используемого в качестве подкласса. Я думаю, вы сможете использовать события. Я думаю, что ответ использует намерения, но я создам только новый экземпляр своей деятельности, который я не хочу. – skinnybrit51

+0

Вы можете легко использовать свою AsyncTask в своем классе, но это полезно, только если вы используете ту же логику из нескольких разных видов деятельности. В этом случае вы можете: 1. использовать общий базовый класс (не активность, а что-то расширяющееся активность), и тогда у вас будет общий метод, который можно вызвать из задачи async. Или еще лучше, если они оба реализуют общий интерфейс, который имеет обратный вызов, как я описал. Передайте ссылку на активность в конструктор AsyncTask и убедитесь, что asyncTask имеет конструктор, который принимает параметр типа интерфейса. –

+0

Ваш последний вариант - полностью вырезать AsyncTask и поместить его в сервис, который вам нужен, чтобы создать новый поток для выполнения фоновой активности (поскольку службы не будут запускаться там, где есть собственный поток по умолчанию). Легкий способ сделать это - создать IntentService, который создает для вас новый поток. –

Смежные вопросы