52

我在 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
                }});
}
4

6 回答 6

82

看起来你在错误的线程上。尝试使用处理程序在正确的线程上更新 GUI。请参阅android.com的 UI 线程示例中的处理昂贵的操作。基本上,您将包装byeSetup在 a 中并使用实例Runnable调用它。Handler

Handler refresh = new Handler(Looper.getMainLooper());
refresh.post(new Runnable() {
    public void run()
    {
        byeSetup();
    }
});
于 2010-07-19T12:36:03.227 回答
6

当更改涉及到主线程(UiThread)。在另一个线程内使用它来更改任何视图。

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

      // TODO your Code 
        et_Pass.setText("");
    }
});
于 2017-11-13T09:15:00.727 回答
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
    }
});
于 2015-01-07T03:17:29.487 回答
2

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

于 2012-05-25T21:36:38.010 回答
1

另一种方法,这次利用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();
于 2017-03-27T22:24:54.080 回答
0

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

address_box.post { address_box.text="my text"}
于 2018-11-01T15:56:07.373 回答