首先,我想出了如何从另一个线程更新UI。我正在使用AsyncTask和Handler类来处理其他任何事情
但是首先我做错了,现在我真的想知道出了什么问题。
所以我的第一次尝试是使用方法MyListener
创建一个java接口updateUI()
,让主活动实现该监听器接口。比我在处理http请求的线程中将主活动注册为侦听器。在请求完成后,我从该线程调用了MyListener.updateUI()
。 updateUI()
使用请求的结果更新一些textview。
这在android中不起作用。而且我没想到。我不知道为什么。 例外告诉我,我必须从UI线程进行这些更新。
我不明白为什么updateUI()
在我从调用者接口实现MyListener.updateUI()
的主要活动调用updateUI()
时不会在UI线程中运行。
你能解释一下这种行为吗?
答案 0 :(得分:3)
我看到你在其他线程中已经执行了http请求,但你没有使用AsyncTask
,对吧?我建议您应该使用该类,在doInBackground
方法中执行http请求(因为它在主线程上工作),并在MyListener.updateUI()
上调用onPostExcute
,因为此方法始终在main中调用线。如果有效,请试试让我知道。
答案 1 :(得分:2)
如果您在MyListener.updateUI()
的{{1}}方法中调用MainActivity
或其他任何其他线程,如果您从另一个线程中执行此操作,则无关紧要,它会抛出异常,因为您只能在应用程序主线程中更新View。要做到这一点,你可以这样做:
onCreate()
将此内容放入您的活动中,并在public static void updateUI(){
((Activity) mContext).runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
// update your UI here and be sure to give the activity context, not getApplicationContext();
}
});
}
中执行类似的操作:
onCreate()
并从你想要的任何线程中调用public static Context mContext;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mContext = this;
}
。
当然,这不是更新界面的唯一方法。您可以查看Android SDK中的AsyncTask
实现。这是一个非常强大的课程,我认为它可以更有效地完成你想做的事情。
答案 2 :(得分:1)
您收到此错误是因为控件仍然在后台线程中...虽然您调用了已在您的activity中实现的接口方法。所以为了将控件恢复到您的UI线程,您需要使用处理程序发布。只需调用活动中的方法,控件就不会从后台线程进入UI线程。
希望这能澄清你的怀疑。