sleep方法不会抛异常。 textView1.setText("zzzzzzzzzzzzzz");这句才会。 异常信息如下,大家应该曾经都见过~: 10-31 11:47:04.118: ERROR/AndroidRuntime(3878): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.我估计是在主线程初始化界面完毕之前其他线程能改UI的内容吧...或许是在onResume执行完毕之前...像什么通过监听器触发或者sleep了几秒后,UI初始化已经完毕了,于是不能在别的线程里改了...
在线程的run方法中使用runOnUiThread来更新TextView Your_Current_Activity.this.runOnUiThread(new Runnable() { public void run() { //update textview here } }); 改变你的 MyUpdateUIThread 构造函数:private TextView textView1; Activity activity; public MyUpdateUIThread(TextView textView1,Activity activity) { super(); this.textView1 = textView1; this.activity=activity; }@Override public void run() { super.run(); activity.runOnUiThread(new Runnable() { public void run() { //update textview here textView1.setText("zzzzzzzzzzzzzz"); } });} 然后在 Main Activity 中创建 MyUpdateUIThread 对象: Thread thread = new Thread(new MyUpdateUIThread(textView,Main.this));
在oncreate和onresume之前view是没有调用invalidate()方法,所以调用到ViewRoot里面的 void checkThread() { if (mThread != Thread.currentThread()) { throw new CalledFromWrongThreadException( "Only the original thread that created a view hierarchy can touch its views."); } }这个方法,所以不会有异常抛出,而settext的字符已经设置进去了,在onresume后得到焦点,再invalidate()就出现了在线程设置的字符串
发一下代码:
package extthread;import android.widget.TextView;public class MyUpdateUIThread extends Thread { private TextView textView1; public MyUpdateUIThread(TextView textView1) {
super();
this.textView1 = textView1;
} @Override
public void run() {
super.run();
textView1.setText("zzzzzzzzzzzzzz");
}}------------------------------
package testtest.test.run;import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import extthread.MyUpdateUIThread;public class Main extends Activity {
TextView textView; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); textView = (TextView) this.findViewById(R.id.textView1);
Thread thread = new Thread(new MyUpdateUIThread(textView));
thread.start(); }
};上面用线程代码不出错!
所以如果你想在非主线程中操作UI,就要在使用消息发送的方式。例:
在主线程中定义handler:Handler h=new Handler(){
public void handleMessage(Message msg){
//你的操作
}
}在非主线程这样使用:
h.sendMessage(Message.obtain()); //也可以新建一个Message对象
楼上的是可以的。以至于你的代码为什么没错,估计是因为把对象传过来了,而对象是在主线程中new的。所以就可以更新了吧。
public void handleMessage(Message msg){
//你的操作
}
}在非主线程这样使用:
h.sendMessage(Message.obtain()); //也可以新建一个Message对象
这种方法可行!
thread.start();
首先看到你这样创建线程时,我震惊了~你的MyUpdateUIThread纯当实现Runnable接口的类来使用了~
直接
Thread thread = new MyUpdateUIThread(textView);
thread.start();
就好了。然后我直接测试下。。发现问题了。。
居然真的能textView1.setText("zzzzzzzzzzzzzz");不报错。
这太操蛋了~于是我分别在onCreate和run方法里加了打印语句Thread.currentThread().getName()
10-31 09:55:15.348: VERBOSE/King(1228): in run : Thread-10
10-31 09:56:33.088: VERBOSE/King(1328): in Activity : main
明明是不同线程是确定了的~
然后我在run方法里加了个sleep()想看看可不可以隔几秒再把“zzzzzzz”更新到UI上去,如下:
public void run() {
super.run();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
textView1.setText("zzzzzzzzzzzzzz");
Log.v("King", "in run : "+Thread.currentThread().getName());
}
这样就出错了。
我也纳闷了。为了不sleep能正常运行。应该是会出错的啊。
建议没试过的童鞋都试一下。。惊天发现啊~
textView1.setText("zzzzzzzzzzzzzz");这句才会。
异常信息如下,大家应该曾经都见过~:
10-31 11:47:04.118: ERROR/AndroidRuntime(3878): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.我估计是在主线程初始化界面完毕之前其他线程能改UI的内容吧...或许是在onResume执行完毕之前...像什么通过监听器触发或者sleep了几秒后,UI初始化已经完毕了,于是不能在别的线程里改了...
都是在onCreate里进行操作。都是不耗时的简单线程。这样有什么意义呢?如果你的线程在onResume之后执行,100%出错。
这句话放到activity里面就没有问题,放到run里面就不行,求解
不神奇。onResume之后就会报错了。比如点击button启动
Your_Current_Activity.this.runOnUiThread(new Runnable() {
public void run() { //update textview here
}
});
改变你的 MyUpdateUIThread 构造函数:private TextView textView1;
Activity activity;
public MyUpdateUIThread(TextView textView1,Activity activity) {
super();
this.textView1 = textView1;
this.activity=activity;
}@Override
public void run() {
super.run();
activity.runOnUiThread(new Runnable() {
public void run() { //update textview here
textView1.setText("zzzzzzzzzzzzzz");
}
});}
然后在 Main Activity 中创建 MyUpdateUIThread 对象:
Thread thread = new Thread(new MyUpdateUIThread(textView,Main.this));
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}这个方法,所以不会有异常抛出,而settext的字符已经设置进去了,在onresume后得到焦点,再invalidate()就出现了在线程设置的字符串
你直接通过一个线程run时,可能onResume()方法还没有回调,此时当然能调用View.setXXX(),在onResume()方法回调后,一定会报异常的。这样就可以解释10L同学的答案了。
onResume里面更新也没报错
基本原理是这样的,但由于这些行为都涉及了很多IPC操作,导致onResume()后,UI Thread建立View 树还没有成功,此时,依旧可以通过线程操作View对象了。不过View添加至窗口后,就只能在UI Thread更新了。
不神奇。onResume之后就会报错了。比如点击button启动加1 , 我这样测试了下, 在UI初始化完毕之后 就不能在线程里修改了..