无法从 AsyncTask 内部触摸外部视图.但并非总是如此



我做了一个AsyncTask,它应该编译一个TextView。这是对我所做的事情的简短回顾。我删除了很多行,所以我希望我没有忘记任何东西。

public class MyClass extends RelativeLayout {
        private TextView messageTextView;

    public MyClass(Context context) {
        super(context);
        init(context); }
    public MyClass(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context); }
    public MyClass(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context); }

    private void init(Context context) {
        createLayoutContent();
                run();
    }
    private void createLayoutContent (Context context) {
        this.setLayoutParams(new RelativeLayout.LayoutParams (RelativeLayout.LayoutParams.MATCH_PARENT, 0));
        messageView = new TextView(context);
        messageView.setText("test");
        this.addView(messageView);
    }
    private void start() {
        new AsyncTask<Void, String, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                try {
                    String s_message = "test2";
                    messageView.setText(s_message);    **// HERE IS WHERE THE ERROR IS //**
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }.execute();
    }
}

在此之后,我将对象直接放在布局中:

    <<...>MyClass
        android:id="@+id/test"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
    />

现在的问题是,在某些应用程序上,这完全有效。一旦活动运行,setContentView(( 就会创建 ui 对象,一切都很好。在其他应用程序上,我不断收到一条错误消息,指出">只有创建视图层次结构的原始线程才能触摸其视图。

我收到此错误,但我不明白为什么在某些应用程序上它工作正常......更奇怪的是,我曾经遇到过通常出错的应用程序突然开始工作,然后在两次正确运行后又回到错误!!

这完全奇怪。

我知道也许细节不足以检测到错误,所以请原谅我,但我检查了我能想到的所有拘留,我找不到它何时有效和何时无效之间的显着差异。也许更多的专家眼睛可以检测到某些东西,解释某些内容或建议我在哪里调试。有人可以帮助我吗?

谢谢。

我不确定为什么它有时有效。但它应该每次都失败。如果 Android 系统决定在 UI 线程中运行您的后台线程代码,则它可能有效。

以下是解决您的问题的方法:将"触摸视图"内容移动到onPostExcution()onProgressUpdate()。UI 只能从 UI 线程内部触摸。AsyncTask非常方便地做到这一点。除doInBackground()之外的所有AsyncTask's方法都在 UI 线程上运行。

因此,切勿直接从doInBackground()更改Views

private void start() {
    new AsyncTask<Void, String, String>() {
        @Override
        protected String doInBackground(Void... params) {
            try {
                String s_message = "test2";
                return s_message;
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
        }
        @Override
        protected void onPostExecute(String s) {
            messageView.setText(s);
        }
    }.execute();
}

最新更新