- 首先,线程之间本来就可以相互修改对象属性,因为对象存储在堆内存中,堆内存本来就是线程共享的。看下面这段代码的运行结果,就明白了。
public class HandlerTest {
static class Message {
String name;
int age;
}
public static void main(String[] args) {
Message msg = new Message();
msg.name = "Tom";
msg.age = 20;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
msg.name = "Bruce";
msg.age = 27;
}
}, "自定义子线程");
t.start();
try {
Thread.sleep(100);
while (msg != null) {
System.out.println(Thread.currentThread().getName() + " 获取msg:" + msg.name + " " + msg.age);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
-
所以,Handler机制的作用并不是线程间通信。必然有其他作用。众所周知,如果子线程直接修改UI,会抛出异常:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
具体抛异常的代码,参考:Android子线程真的不能刷新UI吗?(一)复现异常。根据上面的Java例子,直接写一段子线程间接修改UI的代码:
public class MainActivity extends AppCompatActivity { Message msg; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); msg = new Message(); Thread thread = new Thread(new Runnable() { @Override public void run() { msg.what = 99; } }); thread.start(); try { Thread.sleep(50); if (msg.what == 99) { TextView tv = findViewById(R.id.tv); //原本显示的是"Hello World!",现在改为"xxx" tv.setText("xxx"); } } catch (InterruptedException e) { e.printStackTrace(); } } }
看下运行效果:
说明,即使是解决子线程修改UI的异常,也没有必要用Handler那一套。所以,Handler消息机制的主要作用,也不是解决子线程不能更新UI的异常。Handler消息机制的作用,我们下一篇再讨论。
深入理解MessageQueue
android之handler切换线程终极篇