Android 无法从异步任务内部触摸外部视图。。。但并非总是如此

Android 无法从异步任务内部触摸外部视图。。。但并非总是如此,android,Android,我做了一个异步任务,应该编译一个TextView。这是对我所做工作的简短回顾。我删除了很多行,所以我希望我没有忘记任何东西 public class MyClass extends RelativeLayout { private TextView messageTextView; public MyClass(Context context) { super(context); init(context); } public

我做了一个异步任务,应该编译一个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扩展了RelativeLayout{
私有文本视图messageTextView;
公共MyClass(上下文){
超级(上下文);
init(上下文);}
公共MyClass(上下文上下文、属性集属性、int-defStyle){
超级(上下文、属性、定义样式);
init(上下文);}
公共MyClass(上下文、属性集属性){
超级(上下文,attrs);
init(上下文);}
私有void init(上下文){
createLayoutContent();
run();
}
私有void createLayoutContent(上下文){
this.setLayoutParams(新的RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,0));
messageView=新文本视图(上下文);
messageView.setText(“测试”);
this.addView(messageView);
}
私有void start(){
新建异步任务(){
@凌驾
受保护的Void doInBackground(Void…参数){
试一试{
字符串s_message=“test2”;
messageView.setText(s_message);**//这里是错误所在//**
}捕获(格式错误){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}捕获(JSONException e){
e、 printStackTrace();
}
返回null;
}
}.execute();
}
}
之后,我将对象直接放在布局中:

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

现在的问题是,在一些应用程序上,这一点非常有效。一旦活动运行,setContentView()就会创建ui对象,一切正常。 在其他应用程序上,我不断收到一个错误,上面说“只有创建视图层次结构的原始线程才能接触其视图。”

我得到了这个错误,但我不明白为什么在一些应用程序上它工作良好。。。 更奇怪的是,有一次我碰巧发现,通常出现错误的应用程序突然开始工作,然后在两次正确运行后返回错误

这太奇怪了

我知道可能细节不足以检测错误,所以请原谅,但是我检查了所有我能想到的细节,我没有发现它工作时与不工作时的显著差异。也许更专业的眼睛可以发现一些东西,解释一些东西,或者建议我在哪里调试。 有人能帮我吗


非常感谢。

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

以下是解决问题的方法: 将“触摸视图”内容移动到
onPostExecution()
onProgressUpdate()
。 UI意味着只能从UI线程内进行触摸。AsyncTask有助于非常方便地完成此任务。除了
doInBackground()
之外,所有
AsyncTask的
方法都在UI线程上运行

因此,从不直接从
doInBackground()
更改
视图

private void start(){
新建异步任务(){
@凌驾
受保护字符串doInBackground(无效…参数){
试一试{
字符串s_message=“test2”;
返回s_消息;
}捕获(格式错误){
e、 printStackTrace();
}捕获(IOE异常){
e、 printStackTrace();
}捕获(JSONException e){
e、 printStackTrace();
}
返回null;
}
@凌驾
受保护的void onPostExecute(字符串s){
messageView.setText;
}
}.execute();
}

ooh!!onPostExecute拯救了我的一天!非常感谢。关于它为什么起作用。。。我不知道,但我确信它在市场上目前在线的一些应用程序上有效。。。只是为了确保我无论如何都会编辑它们。除了
doInBackground()
以外的任何方法。因为此方法正在后台线程中运行。
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();
}