android的消息机制之学习笔记
来源:互联网 发布:洛奇英雄传帧数优化 编辑:程序博客网 时间:2024/05/22 00:25
了解Android的消息机制,主要是了解handler,looper和MessageQueue的运行机制。
MessageQueue类
Message是消息的载体,MessageQueue则用来存放Message,虽说MessageQueue叫消息队列,其实它是由单链表实现的,因为单链表容易进行数据的增加和删除。
looper类
looper在安卓消息机制中主要扮演者消息循环的角色,在looper的构造方法中会生成 一个MessageQueue,looper则不断的循环检测这个消息队列,当检测到消息队列有新消息到来时,它会通知线程来读取并处理这个消息,否则它就一直阻塞在那里。一个线程对应着一个looper。
private Looper(boolean quitAllowed){ mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread();}
Handler类
handler是消息的接收者和处理者,通过handler,任务可以传递到另外一个线程进行处理。用户再源线程通过handler将消息传递到消息队列中,同时在目的线程通过handler的回调方法handleMessage()进行消息的处理。最常见的是将子线程中需要进行UI更新的任务传递到主线程进行处理。在安卓中,子线程是无法进行UI操作的,只能在主线程中进行UI的操作。这是因为UI控件不是线程安全的,在多线程并发访问的情况下会出现不可预期的状况。Android提供了handler,让我们统一的将各个线程的UI操作任务传递到主线程中进行。当然,handler不是专门用来进行UI操作的,只是大多数开发者常用handler进行UI操作。
整体分析
首先是创建handler对象。一个线程内可以用一个也可以用多个handler对象来进行处理消息。构造handler对象需要两个参数,一个是线程的looper对象,一个是消息的处理函数。handler只能对某一个线程的looper对象发送消息,所以必须指明looper参数,如果不指定looper对象,则默认使用当前线程的looper对象。另一个参数处理函数Callback则不是必须得。这个Callback 是Runnable类。构建完handler后就可以通过handler发送消息了,发送消息方法主要有两大类send和post。
public final boolean sendMessage(Message msg) public final boolean sendEmptyMessage(int what) public final boolean sendEmptyMessageDelayed(int what,long delayMills) public final boolean sendMessageDelayed(Message msg,long delayMills) public final boolean sendMessageAtFrontOfQueue(Message msg) ...
这么多send方法归根到底就是把消息插入到消息队列中,并指定了时间。如果指定时间为0,则表示消息要理解处理,消息队列会吧这个消息插入到消息队列的头部。再看看post方法。
public final boolean post(Runnable r){ return sendMessageDelayed(getPostMessage(r),0);}public final boolean postAtTime(Runnable r,long uptimeMills){ return sendMessageAtTime(getPostMessage(r),uptimeMills);}...
可以看到,post方法归根是调用了send方法,只是它把消息处理函数封装到Message中了,一般,post方法用来发送带有处理方法的消息,send方法则用来发送传统的带有消息Id的消息。消息通过handler进行send发送后,会调用MessageQueue的enqueueMessage()方法。
boolean enqueueaMessage(Message msg,long when)
这个方法是干嘛的呢?它是将消息插入到MessageQueue中,它按照消息msg.when来排序,时间早的排在前面。它的源码主要操作就是单链表的插入操作。每插入一条消息,计算是否唤醒处理线程(看时间有没有到)。一个looper可以对应多个handler,所以MessageQueue中可以含有多个目的处理线程。那什么情况下会唤醒处理线程呢,MessageQueue中插入了一条马上要处理的消息,或者在暂停处理消息的情况下,又插入“异步消息”的情况下才会去唤醒处理的线程。那这个“异步消息”是什么消息呢?在Android的MessageQueue类中,有一个enqueueSyncBarrier(long when)方法,调用这个方法会在MessageQueue中插入一个没有handler对象的消息,这个不带handler对象的消息称为 ”SyncBarrier”,在“SyncBarrier”后面的消息都暂停处理。这个时候,如果使用 setAsynchronous()方法给一个消息做上标识,MessageQueue检测到这个标识后,还是会正常处理这个消息。这个设置了标识的消息就是所谓的”异步消息“。消息发送到MessageQueue后,looper就可以检测到这个新消息了。那么如何构建looper对象呢,系统会为主线程自动创建一个Looper对象,但是当用户创建一个子线程时,则需要用户亲自创建Looper对象了。Looper类中有一个静态方法prepare(),调用它会
创建一个Looper对象,并保存在ThreadLocal中,和当前线程绑定在一起。ThreadLocal 是一个模板类ThreadLocal,在Thread类中专门有一个成员用来存储ThreadLocal的数据,通过ThreadLocal就可以在指定线程中存储数据,这个数据数据对于其他线程来说是无法获取到的。在Looper类中,用ThreadLocal存储Looper对象,这样对于不同的线程,它的Looper对象是不一样的。创建了Looper对象后,就要loop()方法开启对其消 息队列的循环检测。这两个方法调用一般在线程的的run()方法中,如
class MyThread extends Thread{ public void run(){ Looper.prepare(); Looper.loop(); }}
loop()方法会循环从MessageQueue中取出消息,然后将消息分发个目的handler。
public static void loop(){ ... for(;;){ Message msg = queue.next(); if(msg == null){ return; } ... msg.target.dispatchMessage(msg); ... }}
loop()通过MessageQueue的next()方法取出消息,next()方法大概逻辑如下:
- 检测MessageQueue第一条消息是不是”Syncbarrier”消息,如果是,寻找MessageQueue中第一个“异步消息”做完当前处理消息,如果不是,则将第一条消息作为当前处理消息。
- 如果当前处理消息不为null,检测消息处理时间是否到了。如果没有,继续等待,如果到了,next()方法返回该消息并退出。
- 如果当前处理消息为null,标示队列中没有可以处理的消息,设置等待时间为-1(表示永久等待)。通过next()方法取出消息后,就可以调用handler的dispatchMessage(msg)进行处理消息的。
public void dispatchMessage(Message msg){ if(msg.callback != null){ handleCallback(msg); } else { if(mCallback != null){ if(mCallbacl.handlerMessage(msg)){ return; } handlerMessage(msg); }}
从源码可看出,消息给消息中自带的回调方法进行处理。如果消息中没有自带回调方法,且用户在handler定义了回调方法,则消息交给这个回调方法处理。否则,调用Handler自己的handlerMessage()的方法,这个方法缺省不做任何事。android消息机制java层处理将完了,对于其native层的实现,貌似是通过匿名通道来实现线程间通信的。这里不再讨论。
- android的消息机制之学习笔记
- Android学习笔记:Android消息处理机制之Handler介绍
- 安卓学习笔记之Android消息机制
- android学习笔记(15)Android消息机制
- 雾山的Android学习笔记---消息机制(一)
- 雾山的Android学习笔记---消息机制(二)
- 雾山的Android学习笔记---消息机制(三)
- 雾山的Android学习笔记---消息机制(三) .
- 雾山的Android学习笔记---消息机制(二) .
- 雾山的Android学习笔记---消息机制(一) .
- C++学习笔记之WINDOWS消息机制
- MFC学习笔记之消息映射机制
- Android学习笔记--消息处理机制
- Android异步消息处理机制学习笔记
- Android笔记之消息处理机制
- 消息机制学习笔记
- 【Android笔记】消息机制
- Android消息机制笔记
- 海康转码
- android游戏开发5-5 实现背景图的沿x轴移动
- 直接插入排序
- javascript作用域链
- 安卓开发基础之java基础中this关键字解析
- android的消息机制之学习笔记
- ubuntu系统root登录
- Linux追求记(1)
- Spark生态之Alluxio学习9---Auuxio(Tachyon)的优点
- STL_学习_vector容器源码解析
- 关于xcode7.3设置启动图片的小提示
- 叠罗汉II
- 解决html输入中文后,在myEclipse中打开乱码问题。
- poj之旅——1979