CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及视图

时间:2010-07-19 10:13:05

标签: android handler android-asynctask

我在Android中遇到以下错误的问题:

  

CalledFromWrongThreadException;:仅   创建一个的原始线程   视图层次结构可以触及其视图

当我尝试在我的Activity中更新Textview时,似乎会发生这种情况,更新TextView的调用来自我的Activity,但我仍然遇到上述错误。

我喜欢这样:

的onCreate() - 设置按钮和文本视图。

onStateChange() - 一个关于状态更改通知的侦听器,当收到通知时,如果将TextView更改为说一些不同的文本。

当我收到新文本的通知时,我尝试将TextView更改为:

((TextView)findViewById(R.id.title)).setText("Some Text");

但是我得到了上面的错误。

从谷歌搜索,似乎我应该使用处理程序来更改TextView或者使用AsyncTask?

有谁可以解释哪一个更好用,为什么?

编辑:添加代码片段:


     public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);  

            setContentView(R.layout.my);

            getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.my_title);  

            ((TextView)findViewById(R.id.time)).setText("Hello Text");


            findViewById(R.id.keyboardimage).setOnClickListener(new OnClickListener() {
                public void onClick(View v) {

                    Intent dialIntent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:"));
                    startActivity(dialIntent);

                        dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.FLAG_SOFT_KEYBOARD));
                        dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));       
                }
        });

     }

//CallBacks from running Service

private final ICallDialogActivity.Stub iCallDialogActivity = new ICallDialogActivity.Stub(){

@Override
public void onStateChanged(int callState)
                throws RemoteException {    
            switch(callState){
            case GlobalData.CALL_STATUS_IDLE:

                break;

            case GlobalData.CALL_STATUS_DISCONNECTING:
                byeSetup();
                break;
    } 

};

public void byeSetup(){

            ((TextView)findViewById(R.id.time)).setText("Bye Text");

            findViewById(R.id.keyboardimage).setOnClickListener(new OnClickListener() {
                public void onClick(View v) {
                    //Void the Button
                }});
}

6 个答案:

答案 0 :(得分:74)

看起来你的错误。尝试使用Handler更新右侧线程上的GUI。请参阅android.com上的Handling Expensive Operations in the UI Thread示例。基本上,您可以将byeSetup包裹在Runnable中,并使用Handler实例调用它。

Handler refresh = new Handler(Looper.getMainLooper());
refresh.post(new Runnable() {
    public void run()
    {
        byeSetup();
    }
});

答案 1 :(得分:3)

为了清晰起见,扩展了willcodejavaforfood的答案。实施...

我让这个工作,下面是我做的。我在服务中运行多个处理线程,因此在Activity中运行的其他解决方案不起作用,例如runOnUiThread(new Runnable(){} ...

将它放在服务类的顶部,以便在此类的任何位置都可以访问:

Handler handler;

将它放在服务类onCreate方法或服务主线程上加载的东西

handler= new Handler(Looper.getMainLooper());

将此内容添加到您的其他帖子中以“回发”代码,以便在UI或服务UI中运行(请注意其名称):

handler.post(new Runnable() {
    public void run() {
        playNext(); //or whatever method you want to call thats currently not working
    }
});

答案 2 :(得分:2)

对于其他人,只需替换byeSetup();使用您的代码语句或方法。 byeSetup()是一个示例方法。希望它能节省你的一些时间。

答案 3 :(得分:1)

此方法仅适用于活动,当更改涉及主线程( UiThread )时效果更佳。在另一个Thread内部使用它来改变任何视图。

runOnUiThread(new Runnable() {
    @Override
    public void run() {

      // TODO your Code 
        et_Pass.setText("");
    }
});

答案 4 :(得分:0)

另一种方法,这次使用android.os.Message

android.os.Handler定义为您的活动中的字段:

private final Handler myTextHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message stringMessage) {
        textView.append((String) stringMessage.obj);
        return true;
    }
});

然后从你的其他线程中提取它:

Message stringMessage = Message.obtain(myTextHandler);
stringMessage.obj = "Hello!";
stringMessage.sendToTarget();

答案 5 :(得分:0)

您可以使用view的内置post方法来更新其他线程中的内容,就像我在kotlin中使用编辑文本一样。

div