Для каждой ошибки потока может быть создан только один цикл, асинхронная задача

#android #multithreading #android-asynctask #looper

#Android #многопоточность #android-asynctask #цикл

Вопрос:

Код в нижней части этого сообщения запускается следующей строкой кода.

 new MasterClickAsyncTask(main).execute(position);
  

Приведенная ниже часть кода doInBackground вызывает метод, содержащий цикл for, отсюда и необходимость в Looper.prepare() .

Этот код работает нормально первые несколько раз, когда он вызывается, но затем выдает следующую ошибку:

10-15 22:50:24.752: ОШИБКА / AndroidRuntime(9258): Вызвано: java.lang.RuntimeException: для каждого потока может быть создан только один цикл

Я пытался поместить Looper.getMainLooper().quit(); и несколько других подобных вещей в различные части AsyncTask, но это только привело к немедленному сбою.

Любая помощь?

Код:

 import java.io.IOException;
import java.net.MalformedURLException;
import org.json.JSONException;
import android.os.AsyncTask;
import android.os.Looper;
import android.view.View;

public class MasterClickAsyncTask extends AsyncTask<Integer, Void, Void> {

    Master selectedMaster;
Main main;
MasterGridView masterGridView;
Integer i;
DiscogProxy discogProxy = new DiscogProxy();

MasterClickAsyncTask(Main main){
    this.main = main;
    this.masterGridView = main.getMasterGridView();
}

@Override
    protected void onPreExecute() {
        main.progressBar.setVisibility(View.VISIBLE);
    }
       @Override
        protected Void doInBackground(Integer... params) {
            masterGridView.getSelectedView();
            Globals.selectedMaster = (Master)(masterGridView).getItemAtPosition(params[0].intValue());
            Globals.selectedMaster.getVersionListView().getVersionList().clear();
               Looper.prepare();
              try {
                  Globals.selectedMaster.getVersionListView().populateVersionList();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (JSONException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
               //Looper.getMainLooper().quit();
        return null;    
        }       

@Override
protected void onPostExecute(Void result) {
     main.populateAlbumVersionsView();
     main.progressBar.setVisibility(View.GONE);
}   
}
  

Ответ №1:

Цикл не имеет ничего общего с циклами for . Цикл — это часть системы Android, которая управляет потоком пользовательского интерфейса. Есть несколько вещей, которые не будут работать без подготовки цикла, но в целом этого лучше избегать Looper.prepare(); , если в этом нет крайней необходимости. Гораздо лучше использовать async doInBackground для выполнения обработки данных или других более длительных операций, а затем обновлять пользовательский интерфейс с onPostExecute помощью and onProgressUpdate .

Короче говоря, если вы каким-либо образом не используете пользовательский интерфейс, вам не нужно вызывать цикл. Если вам приходится вызывать петлитель, вам, вероятно, потребуется изменить структуру работы ваших фоновых потоков.

Комментарии:

1. И если вы пытаетесь изменить пользовательский интерфейс изнутри своей AsyncTask, вызовите publishProgress из doInBackground, а затем внесите изменения в onProgressUpdate .

2. Я смог извлечь все элементы пользовательского интерфейса из своего метода doInBackground() с минимальными усилиями, и все это работает нормально. Большое вам спасибо за ваш совет!