AsyncTask «Только исходный поток, создавший иерархию представлений, может касаться его представлений». - PullRequest
9 голосов
/ 19 сентября 2011

Я пытаюсь изменить содержимое Spinner в AsyncTaks, но не могу, и Logcat записывается "09-19 16: 36: 11.189: ОШИБКА / ОШИБКА (6078): Только исходный поток, создавший иерархию представленияможет коснуться его взглядов. ".

public class GetGroups extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... params) {
        Spinner combo = (Spinner) findViewById(R.id.group_combo);

        setGroups(combo);

        return null;
    }

    @Override
    protected void onPostExecute(Void unused)
    {
        super.onPostExecute(unused);


        Spinner combo = (Spinner) findViewById(R.id.severity_combo);

        combo.setSelection(1);

        //updateGroups();
        //if (!isFinishing())
        //{
            /*Spinner combo = (Spinner) findViewById(R.id.group_combo);
            ProgressBar pg = (ProgressBar) findViewById(R.id.loading_group);

            pg.setVisibility(ProgressBar.GONE);
            combo.setVisibility(Spinner.VISIBLE);

            combo.setSelection(0);*/
        //}
    }
}
}

А функция setGroups:

 public void setGroups(Spinner combo) {

    try {
        DefaultHttpClient httpClient = new DefaultHttpClient();

        HttpPost httpPost = new HttpPost(this.object.url);

        List<NameValuePair> parameters = new ArrayList<NameValuePair>(2);
        parameters.add(new BasicNameValuePair("user", this.object.user));
        parameters.add(new BasicNameValuePair("pass", this.object.password));
        parameters.add(new BasicNameValuePair("op", "get"));
        parameters.add(new BasicNameValuePair("op2", "groups"));
        parameters.add(new BasicNameValuePair("other_mode", "url_encode_separator_|"));
        parameters.add(new BasicNameValuePair("return_type", "csv"));
        parameters.add(new BasicNameValuePair("other", ";"));

        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters);

        httpPost.setEntity(entity);

        HttpResponse response = httpClient.execute(httpPost);
        HttpEntity entityResponse = response.getEntity();

        String return_api = this.object.convertStreamToString(entityResponse.getContent());

        String[] lines = return_api.split("\n");

        ArrayList<String> array = new ArrayList<String>();

        for (int i= 0; i < lines.length; i++) {
            String[] groups = lines[i].split(";", 21);

            this.pandoraGroups.put(new Integer(groups[0]), groups[1]);

            array.add(groups[1]);
        }

        ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_spinner_item,
            array);
        combo.setAdapter(spinnerArrayAdapter);
    }
    catch (Exception e) {
        Log.e("ERROR THE ", e.getMessage());

        return;
    }
}

Что не так?Спасибо.

Ответы [ 4 ]

26 голосов
/ 02 мая 2013

Как упоминал Питер, вы не можете получить доступ к представлениям, используя doInBackground(). Вы можете сделать это внутри onPostExecute() однако. Вот где вы должны работать с результатами doInBackground() возврат, насколько я знаю.

Я столкнулся с этой проблемой и исправил ее, переместив код модификации представления в onPostExecute().

Для тех из вас, кто начинает заниматься разработкой для Android:
- doInBackground(): все, что происходит внутри другого потока (на заднем плане), отличного от основного / исходного потока, в котором работают ваши представления / фрагмент / действие (в этом и заключается смысл AsyncTask ==>, вы не можете касаться представлений!
- onPostExecute(): теперь фоновые вещи сделаны, теперь они возвращаются в основной поток / ветку ветки ==> вы можете прикоснуться к просмотру!

10 голосов
/ 19 сентября 2011

Вы пытаетесь получить доступ к компонентам пользовательского интерфейса (View) из фонового потока в вашем случае в методе doInBackground(). Вам запрещено это делать .

3 голосов
/ 25 марта 2015

Немного подробнее

Проблема :

  • Элементы пользовательского интерфейса могут быть изменены только в потоке пользовательского интерфейса.Единственным исключением является их метод postInvalidate() (и его варианты), который может быть выполнен вне потока пользовательского интерфейса
  • ошибка, которую вы получаете, вызвана попыткой изменить элемент пользовательского интерфейса (aView) извне потока пользовательского интерфейса - doInBackground() работает в фоновом потоке

Решение :

  • изменить представления в методе onPostExecute() - он работает в потоке пользовательского интерфейса
  • получить ссылку на Activity ииспользуйте его runOnUiThread(Runnable) метод
  • в зависимости от модификации используйте один из View 'post...() методов
3 голосов
/ 25 марта 2015

Если вы хотите показать прогресс во время фонового процесса, ни один из предыдущих ответов не дает подсказки: когда вызывается OnPostExecute, все заканчивается, поэтому нет необходимости обновлять статус загрузки.

Итак, вы должны переопределить onProgressUpdate в своей AsyncTask и быть уверенным, что второй объект не пустота, а целое число или строка, которая читается onProgressUpdate. Например, используя String:

public class MyAsyncTask extends AsyncTask<Void, String, Void> {

    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        if (values != null && values.length > 0) {
            //Your View attribute object in the activity
            // already initialized in the onCreate!
            mStatusMessageView.setText(values[0]);
        }
    }
}

Чем в фоновом методе вы вызываете publishProgress(value as String), который автоматически вызывает onProgressUpdate метод, который использует основной поток пользовательского интерфейса:

@Override
protected Boolean doInBackground(Void... params) {
    your code...
    publishProgress("My % status...");
    your code...
    publishProgress("Done!");
}

В общем, когда вы объявляете AsyncTask, вы должны указать классы <Params, Progress, Result>, которые передаются основным методам, это могут быть ваши собственные классы или просто классы Java:

  • doInBackground(Params... params)
  • onProgressUpdate(Progress... value)
  • onPostExecute(Result... success)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...