AsyncTask не может работать в потоке Android - PullRequest
1 голос
/ 22 октября 2011

Я использую AsyncTask для изменения текста TextView следующим образом:

    private class LongOperation extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... urls) {
        String response = "";
        for (String url : urls) {
            response += url;
        }
        return response;
    }

    @Override
    protected void onPostExecute(String result) {
        textView.setText(result);
    }
}

Все будет хорошо, если я вызову его в событии OnClick:

 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    textView = (TextView) findViewById(R.id.txt);
    Button button = (Button)this.findViewById(R.id.button);
    button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
          new LongOperation().execute(new String[]{"Hello"});
        }
      });
   }

Но проблема, когда я его вызвалв моей теме программа принудительно закрывалась

this.closeButton.setOnClickListener(new OnClickListener() {
         @Override
        public void onClick(View v) {
          Thread t= new Thread(){               
           @Override
             public void run(){                                     
              try{
                    //Do something
                    //Then call AsyncTask
                new LongOperation().execute(new String[]{"Hello"});

               }catch(Exception e){}
         }
        };      
         t.start();
        }
      });

Где я не прав?Я не понимаю, как разница вызова AsyncTask в потоке или нет.

Ответы [ 3 ]

8 голосов
/ 22 октября 2011

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

Когда вы вызываете AsyncTask.execute () , ваш предоставленный AsyncTask.onPreExecute вызывается в главном потоке, поэтому вы можете выполнить настройку пользовательского интерфейса.

Далее Метод AsyncTask.doInBackground вызывается и выполняется в своем собственном потоке.

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

Если вам нужно обновить пользовательский интерфейс из AsyncTask.doInBackground метода, вызовите AsyncTask.publishProgress , который вызовет onProgressUpdate в основном потоке.

2 голосов
/ 22 октября 2011

Когда вы вызываете его из потока пользовательского интерфейса, связанный Context является запущенным Activity. Когда вы вызываете его из обычного потока, с этим потоком не связывается действительный Context. AsyncTask выполняется в своем собственном потоке, вы не должны создавать свой собственный поток. Если это фактический код, то вы неправильно поняли пункт AsyncTask. Ищите учебники о том, как его использовать.

1 голос
/ 22 октября 2011

В дополнение к тому, что сказали другие: я думаю, что вы можете использовать AsyncTask для запуска задачи в другом потоке, даже если вы запускаете AsyncTask из другого потока, отличного от уже созданного пользовательского интерфейса.

Но в этом случае единственным способом вы сможете только косвенно изменить пользовательский интерфейс, например: каким-либо образом передать обработчик текущей операции в этот экземпляр AsyncTask и отправить ему сообщения (сообщения-обработчики)обрабатываться в потоке пользовательского интерфейса).Или используйте широковещательные намерения, чтобы Activity соответствующим образом ловила и обновляла пользовательский интерфейс и т. Д. Эти решения кажутся излишними.

...