关于android消息处理的个人理解
1、thread线程,主要负责调度整个消息循环,即消息循环的场所。
分为普通线程,消息线程(Looperthread)。
普通线程就是从Thread派生的线程。
消息线程(Looperthread):首先从Thread派生,然后在run方法中调用Looper.preapare()和Looper.loop方法;一个消息线程大概如下所示:
classLooperThreadextendsThread{
publicHandlermHandler;
publicvoidrun(){
Looper.prepare();
mHandler=newHandler(){
publicvoidhandleMessage(Messagemsg){
//processincomingmessageshere
}
};
Looper.loop();
}
}
在run()方法中的Handler变量负责消息的处理。当然此变量的初始化,可以放在其他地方,比如,直接在声明的时候使用匿名类来初始化。采用如下所示的方式:
publicHandlermHandler=newHandler(){
publicvoidhandleMessage(Messagemsg){
//yourprocessmethod
}
}
2、looper,消息泵,不间断的从messageQueue中抽取Message,并进行message的分发。
一个looper中包含了一个MessageQueue,其所处理的Message都是从这个消息队列中取出的。
另外还包含了一个ThreadLocal变量,privatestaticfinalThreadLocalsThreadLocal=newThreadLocal();从本质上来说一个Looper就是一个ThreadLocal,
从Looper的myLooper()方法可以知道:
publicstaticfinalLoopermyLooper(){
return(Looper)sThreadLocal.get();
}
从prepare()可以得知,一个线程中只能有一个Looper:
publicstaticfinalvoidprepare(){
//当已经设置过looper则会抛出异常。
if(sThreadLocal.get()!=null){
thrownewRuntimeException("OnlyoneLoopermaybecreatedperthread");
}
sThreadLocal.set(newLooper());
}
构造函数代码如下:
privateLooper(){
mQueue=newMessageQueue();
mRun=true;
mThread=Thread.currentThread();
}
从构造函数可知,在prepare的时候会创建一个新的MessageQueue,并将looper的线程变量设置为当前正在运行的线程,也就是调用Looper.prepare()方法的线程。
Looper的主线程处理,主要有以下两个方法:
publicstaticfinalvoidprepareMainLooper(){
prepare();
setMainLooper(myLooper());
if(Process.supportsProcesses()){
myLooper().mQueue.mQuitAllowed=false;
}
}
privatesynchronizedstaticvoidsetMainLooper(Looperlooper){
mMainLooper=looper;
}
这两个方法都不能被应用程序使用,在ActivityThread的main()方法中调用了prePareMainLooper()方法:
publicstaticfinalvoidmain(String[]args){
SamplingProfilerIntegration.start();
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThreadthread=newActivityThread();
thread.attach(false);
Looper.loop();
if(Process.supportsProcesses()){
thrownewRuntimeException("Mainthreadloopunexpectedlyexited");
}
thread.detach();
Stringname=(thread.mInitialApplication!=null)
?thread.mInitialApplication.getPackageName()
:"<unknown>";
Slog.i(TAG,"Mainthreadof"+name+"isnowexiting");
}
main()方法作为应用程序的入口,在这里设置了主线程的looper。注:在ActivityThread中加载了应用程序的启动activity,因此主线程也可以叫做UI线程。
loope()方法是一个无限循环,下面是其代码:
publicstaticfinalvoidloop(){
//获取当前线程的looper
Looperme=myLooper();
MessageQueuequeue=me.mQueue;
while(true){
//获取下一个消息
Messagemsg=queue.next();//mightblock
//如果消息不是null,并且消息的handler为null,则退出,说明是一个空消息,则退出循环。
if(msg!=null){
if(msg.target==null){
//Notargetisamagicidentifierforthequitmessage.
return;
}
。。。。
//分发消息,使用消息的handler进行消息的分发操作
msg.target.dispatchMessage(msg);
。。。。。
//清空消息
msg.recycle();
}
}
}
3、Message,代表消息包含了消息的类型(what属性确定,在每个线程中唯一),消息的参数(共两个分别为arg1,arg2,int型),以及一个Bundle对象用于传递Object类型数据。
Message定义了需要被处理的时间(when属性,long型,该时间基于手机开机时间,在开机时间多长时间后进行消息处理),处理目标(target,Handler型,target进行消息的分发处理)
回调操作,callback,Runnable类型,如果指定了此属性在target进行消息分发时,会执行该回调的run方法,而不进行Message的what信息判断和消息参数的处理。
Message的获取方法:
1)、构造方法,newMessage();不推荐使用
2)、obtain()系列方法,在该系列的方法中设置了Message的各种参数,具体配置参考代码。该方法推荐使用。
Message仅仅作为需要传递的信息的一个载体,同时指定需要处理该信息的target,target进行消息的分发处理。
4、MessageQueue,消息队列(其实是一个链表结构,使用Message类型的next变量进行连接,在此链表中,每个数据按照要执行的时间从大到小进行排序),负责消息的缓存和消息从消息队列中的取出操作。
每一个消息都按照执行时间大小插入到列表中,这样可以保证需要立即执行的消息得到及时的执行。
从消息队列中取出消息操作,首先会判断是否当前消息需要被执行(通过消息的执行时间和当前时间进行比较)。
消息队列的创建是在构建Looper的时候进行创建的。这样可以保证一个线程中只有一个消息队列,而每个消息可以有不同的handler,也就是一个线程可以有多个Handler。
5、Handler,消息的处理者,负责消息的发送和处理,实现根据消息进行UI更新,文件读取等操作。
1)Handler的构建。a)、继承Handler类,并重写handleMessage方法。b)、实现Handler类中的Callback接口,并实现其handleMessage方法。,其中第一种方法可以通过构建一个新的Handler子类,然后创建新子类的变量,或者通过使用匿名类方法创建变量的方法来创建Handler变量。
第二种方法使用Handler的类先实现Handler的Callback接口,然后在创建Handler变量的时候,使用带参数的Handler构造方法,并将使用Handler类的this变量传递给构造方法。
两种方法的示例分别如下:
//第一种方法
publicclassActivity1extendsActivity{
publicHandlerhandler=newHandler(){
publicvoidhandleMessage(Messagemsg){
//yourprocesscode
}
}
********
}
//第二种方法,实现Callback接口
publicclassActivity2extendsActivityimplementsHandler.Callback{
publicbooleanhandleMessage(Messagemsg){
//yourprocesscode
}
//创建变量时可以使用下面两种方法的任意一种
Handlerhandler=newHanlder(this);
Handlerhandler2=newHandler(Looper.myLooper(),this);
******
}
Handler的dispatchMessage方法,负责消息的分发,调用具体的消息处理函数
publicvoiddispatchMessage(Messagemsg){
//如果message的回调不是null,则执行message的callback
if(msg.callback!=null){
handleCallback(msg);
}else{
//如果避免子类化回调不是null,则执行此回调
if(mCallback!=null){
if(mCallback.handleMessage(msg)){
return;
}
}
//如果子类化回调没有执行成功,则执行子类的handleMessage
handleMessage(msg);
}
}
sendMessage**()方法,用于将消息插入到消息队列中。并设定消息执行的事件,如果传递的是一个没有target的消息则会终止Looper的loop操作,也就是说会终止整个消息循环。
post*()方法都会创建一个新的message,并在指定的时间执行消息。在这些方法中指定了Message的callback方法,因此需要执行的操作就是callback的中的run方法。
6、activity:UI,所有的UI都在一个线程中,即UI线程。因此在Activity中创建的Handler变量也属于UI线程,因此通常情况下在使用handler进行Ui更新操作可以成功就是因为这个原因。
UI线程是由android在启动应用程序的时候创建的。
7、消息循环的过程:
1、构建消息线程,在调用Looper.prepare()方法时创建了MessageQueue变量。
2、构建Handler变量,并重写handleMessage方法,在构建Handler变量时会将Looper的MessageQueue变量传递给hanler。
3、创建工作者线程,在线程的run方法中创建Message变量,示例代码如下:
Messagemsg=handler.obtain();
//设置msg的参数,一下为参考代码,根据具体情况可以设置不同的值
msg.what=1;
msg.arg1=2;
msg.arg2=3;
Bundledata=newBunlde();
Bundlebundle=newBundle();
//调用bundle的put方法来保存数据
bundle.put**();
msg.setData(data);
//1、此消息的when设置为当前时间(该时间基于开机时间),
//2、设置Message的target为调用sendMessage的handler,
//3、将Message插入到Looper的MessageQueue中
handler.sendMessage(msg);
4、Looper的loop函数进行了从MessageQueue中获取Message,
5、调用Message的target的dispatchMessage()方法分发消息。
6、在dispatch中根据不同条件调用不同的消息处理方法。
7、调用Message的recycle()方法清空消息,到此处消息结束其生命。
获取当前线程的looper:Looper.myLooper();
获取looper的MessageQueue:looper.mQueue;
获取message的target:message.target;
关于Service和线程的关系,service不是一个线程,和activity一样是应用程序的一部分,一般情况下运行在主线程中,如果AndroidMenifest.xml文件中注册sevice时,指定了其android:process属性,则运行在其他进程中。
关于service的参考网址:http://blog.csdn.net/ahcyd008/article/details/7577986