多线程与异步 Main Thread & UI Thread
当程序启动的时候Android会自动创建一个进程和一个线程,这个线程负责界面更新,收集系统事件和用户的操作事件等并分配给对应的组件,所以这个线程非常重要 被称为主线程,因为所的和UI有关的操作都是在这个线程当中进行的所以也被称作UI线程。所以说默认情况下主线程和UI线程指的是同一个线程。For instance, when the user touches a button on the screen, your app's UI thread dispatches the touch event to the widget, which in turn sets its pressed state and posts an invalidate request to the event queue. The UI thread dequeues the request and notifies the widget that it should redraw itself.
Android的UI系统参考了很多SWT的设计模式。比如,UI线程机制,底层JNI实现 etc.
Android 的UI系统是非线程安全的,意思是说只有创建UI的线程(也就是主线程)才可以对UI进程操作。如果我们在其它线程中执行了一些操作,而这些操作的结果又需要通过UI展现给用户,必需把这更新UI的操作转移到到UI线程中执行。
很多Java起步的程序员对UI线程中的"消息循环"会感觉陌生。其实就是在线程内部有一个死循环一直监听系统事件(用户的操作等)并把任务分发给对应的组件(有兴趣的可以看看NDK附带的native-activity的一个sample,在c中的实现方式就是一个while(1)的死循环)。主线程通过Looper实现了消息的循环处理。
The ralationship between Handler,Message,MessageQueue and Looper?如果一个线程里边有一个死循环,那么这个循环就会一直在死循环里边循环,并且这个线程不会过多的cpu资源,那么这个线程肯定的阻塞的。如果线程只是一直循环没有什么意义,实际情况通常需要线程根据不同的条件运行不同的方法。我们通常的作法可能会加一个switch开关,根据条件的不同去调用不同的方法。
线程间通信(最常见的就是,worker线程需要更新UI),这个时候实际是包含两个内容:一,数据的传递;二,方法的传递; Android中的Message用于数据传递,而Handler就是方法传递(其实是方法的执行者,Handler会把这个方法放到Handler所在的线程当中去执行);MessageQueue是Message的容器和Java中的Queue一样都是容器,只不过Message Queue是专门用于装载Message的容器。Looper则是一个线程中的死循环用于管理MessageQueue,它负责阻塞读取MessageQueue中的信息(如果MessageQueue中没有信息会一直在那里),挨个读取并把这个Message分发给对应的Handler去执行。
通过一个小例子+源码追踪下它们之间是怎么工作的,关系是什么样的
publicclass HandleMessageTrackActivity extends Activity {
finalstaticint SHOW_ALERT =1025;
Activity mActivity;
TextView displayText;
Handler mHandler =new Handler(){
@Override
publicvoid handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case SHOW_ALERT:
showAlert((String)msg.obj);
break;
}
}
};
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity =this;
displayText =new TextView(this);
setContentView(displayText);
displayText.setText("Just ignore me");
new Thread(){
@Override
publicvoid run(){
String Greetings ="Greetings from another Thread";
mHandler.obtainMessage(SHOW_ALERT, Greetings).sendToTarget();
}
}.start();
}
privatevoid showAlert(String content){
AlertDialog.Builder builder =new Builder(mActivity);
builder.setMessage(content);
builder.create().show();
}
}
首先看一下mHandler.obtainMessage(SHOW_ALERT, Greetings).sendToTarget();会执行什么。 通过查看Handler的源码发现执行了下边的代码。
public final Message obtainMessage(int what, Object obj){
return Message.obtain(this, what, obj);
}
接着查看Message中的代码,