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

发布于 2024-09-10 07:14:44 字数 2329 浏览 2 评论 0原文

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

I have an issue with the following error in Android:

CalledFromWrongThreadException;: Only
the original thread that created a
view hierarchy can touch its views

It appears to happen when I try to update a Textview in my Activity, the call to update the TextView is from within my Activity but I still get the above error.

I have it like this:

onCreate()
-sets up the buttons and the text view.

onStateChange() - a listener for notifications about state changes, when this gets notification if changes the TextView to say some different text.

When I get notification of a new text I try to change the TextView as so:

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

But I get the above Error.

From googling it, it appears I should use a handler to change the TextView or maybe use AsyncTask?

Could anyone explain which one would be better to use and why?

EDIT: ADDED CODE SNIPPETS:


     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
                }});
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

巨坚强 2024-09-17 07:14:45

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

For others, just replace byeSetup(); with your code statements or methods. byeSetup() is a sample method. Hope it will save some of your time.

穿透光 2024-09-17 07:14:45

另一种方法,这次使用 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();

Another approach, this time making use of android.os.Message

Have android.os.Handler defined as a field within your activity:

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

Then feed it from your other thread like this:

Message stringMessage = Message.obtain(myTextHandler);
stringMessage.obj = "Hello!";
stringMessage.sendToTarget();
披肩女神 2024-09-17 07:14:45

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

address_box.post { address_box.text="my text"}

You can use view's inbuilt post method to update contents in other thread like I'm using edit text in kotlin.

address_box.post { address_box.text="my text"}
趁微风不噪 2024-09-17 07:14:44

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

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

Look like you are on the wrong thread. Try using a Handler to update the GUI on the right thread. See Handling Expensive Operations in the UI Thread example from android.com. Basically you would wrap byeSetup in a Runnable and invoke it with a Handler instance.

Handler refresh = new Handler(Looper.getMainLooper());
refresh.post(new Runnable() {
    public void run()
    {
        byeSetup();
    }
});
树深时见影 2024-09-17 07:14:44

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

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

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

when the change involves to the main thread (UiThread). Use it inside of another Thread to changes any view.

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

      // TODO your Code 
        et_Pass.setText("");
    }
});
蓝海似她心 2024-09-17 07:14:44

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

我让它工作,下面是我是如何做到的。我在 Service 中运行多个处理线程,因此在 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
    }
});

Expanding on willcodejavaforfood's answer for clarity & implementation...

I got this to work and below is how I did it. I'm running multiple processing threads in a Service so other solutions that run in Activity don't work, like runOnUiThread(new Runnable() {}...

Put this at the top of your service class so it's accessible everywhere in this class:

Handler handler;

Put this in your service class onCreate method or something that loads on Service main thread

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

Put this inside your additional thread to 'post back' code to get run in UI or service UI (whatevers its called):

handler.post(new Runnable() {
    public void run() {
        playNext(); //or whatever method you want to call thats currently not working
    }
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文