CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸视图
我在 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
对于其他的,只需替换 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.
另一种方法,这次使用
android.os.Message
将
android.os.Handler
定义为活动中的字段:然后像这样从其他线程提供它:
Another approach, this time making use of
android.os.Message
Have
android.os.Handler
defined as a field within your activity:Then feed it from your other thread like this:
您可以使用视图的内置 post 方法来更新其他线程中的内容,就像我在 kotlin 中使用编辑文本一样。
You can use view's inbuilt post method to update contents in other thread like I'm using edit text in kotlin.
看起来你走错了线。尝试使用处理程序来更新正确线程上的 GUI。请参阅 android.com 中的处理 UI 线程中的昂贵操作示例。基本上,您可以将
byeSetup
包装在Runnable
中,并使用Handler
实例调用它。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 aRunnable
and invoke it with aHandler
instance.当更改涉及主线程(UiThread)时。在另一个线程内使用它来更改任何视图。
when the change involves to the main thread (UiThread). Use it inside of another Thread to changes any view.
为了清晰起见,扩展了 willcodejavaforfood 的答案实施...
我让它工作,下面是我是如何做到的。我在 Service 中运行多个处理线程,因此在 Activity 中运行的其他解决方案不起作用,例如 runOnUiThread(new Runnable() {}...
将其放在服务类的顶部,以便在此类中的任何位置都可以访问它:
将其放入您的服务类 onCreate 方法或在服务主线程上加载的内容中将
其放入您的附加线程中以“回发”代码以在 UI 或服务 UI(无论其名称如何)中运行:
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:
Put this in your service class onCreate method or something that loads on Service main thread
Put this inside your additional thread to 'post back' code to get run in UI or service UI (whatevers its called):