AsyncTask“只有创建视图层次结构的原始线程才能触及其视图。”

时间:2011-09-19 16:44:11

标签: android exception android-asynctask

我尝试修改AsyncTaks中的Spinner内容,但我不能和Logcat写的“09-19 16:36:11.189:ERROR / ERROR THE(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 个答案:

答案 0 :(得分:26)

如Peter所述,您无法使用doInBackground()访问视图。但是,您可以在onPostExecute()内执行此操作。据我所知,这就是你应该使用结果doInBackground()返回的地方。

我遇到了这个问题并通过将视图修改代码移动到onPostExecute()来修复它。

对于那些开始接受Android开发的人:
   - doInBackground():在另一个线程(在后台)发生的内容与您的views / fragment / activity操作的主/原始线程不同(这是AsyncTask ==&gt;你的全部内容无法触及意见!
   - onPostExecute():现在已经完成了背景资料,这里又回到主/线程主题==&gt;您现在可以触摸视图!

答案 1 :(得分:10)

您正尝试在doInBackground()方法中的案例中从后台线程访问UI组件(View)。你是not allowed to do that

答案 2 :(得分:3)

如果您想在后台进程中显示进度,以前的答案都没有给出提示:当OnPostExecute被调用时,一切都已完成,因此无需更新加载状态。

因此,您必须在AsyncTask中覆盖onProgressUpdate,并确保第二个对象不是Void,而是由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),它会自动调用使用主UI线程的onProgressUpdate方法:

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

更一般地说,当你声明一个AsyncTask时,你必须指定传递给main方法的<Params, Progress, Result>类,这些类可以是你自己的类,也可以只是Java类:

  • doInBackground(Params... params)
  • onProgressUpdate(Progress... value)
  • onPostExecute(Result... success)

答案 3 :(得分:3)

更多细节

<强>问题

  • 只能在UI线程中修改UI元素。一个例外是他们的postInvalidate()方法(及其变体)可以在UI Thread
  • 之外执行
  • 您收到的错误是由尝试从UI线程外部修改UI元素(View)引起的 - doInBackground()在后台线程上运行

<强>解决方案