CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能接触视图
Posted
技术标签:
【中文标题】CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能接触视图【英文标题】:CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch views 【发布时间】:2011-03-17 20:18:47 【问题描述】:我在 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
);
【问题讨论】:
你在子类中吗? onStateChange 在哪里被覆盖? 嗨 Pentium10,它通过 AIDL 接口被覆盖并与服务通信,服务将收到一些更改的通知,然后将告诉 Activity 基于此更新其 TextView。我添加了代码 sn-ps 以更好地演示我正在尝试的内容,该错误似乎非常随机出现,并且在 Activity 处于前台和不在前台时都会出现。 CalledFromWrongThreadException 的可能重复项 【参考方案1】:看起来你在错误的线程上。尝试使用处理程序在正确的线程上更新 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();
);
【讨论】:
看来我不必杀了我。 呼 我觉得 Keshav 的回答比较好。 这比使用runOnUiThread()
更好吗?我可以看到我们不需要对 Activity 的引用。此解决方案还有其他优点吗?【参考方案2】:
当更改涉及到主线程(UiThread)时。在另一个线程中使用它来更改任何视图。
runOnUiThread(new Runnable()
@Override
public void run()
// TODO your Code
et_Pass.setText("");
);
【讨论】:
这应该是可以接受的答案,如果你使用的是Fragment,你可以通过getActivity.runOnUiThread()调用这个方法......【参考方案3】:为了清晰和实施,扩展 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
);
【讨论】:
【参考方案4】:对于其他人,只需替换 byeSetup();使用您的代码语句或方法。 byeSetup() 是一个示例方法。希望它会节省您的一些时间。
【讨论】:
【参考方案5】:另一种方法,这次使用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();
【讨论】:
【参考方案6】:您可以使用视图的内置 post 方法来更新其他线程中的内容,就像我在 kotlin 中使用编辑文本一样。
address_box.post address_box.text="my text"
【讨论】:
以上是关于CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能接触视图的主要内容,如果未能解决你的问题,请参考以下文章