android的消息处理有三个核心类:Looper,Handler和Message。其实还有一个Message Queue(消息队列),但是MQ被封装到Looper里面了
Android.os.Handler
相当于Activity 和runnable的之间的桥梁
android.os.Looper
作用主要是用来循环thread的message,通常调用是通过handler调用,循环message
android.os.Message
作用是提供两个int,一个object,能够被handle调用传值
下面详细讲讲
先讲Message
Message 主要有6个参数,
public int what;
public int arg1;
public int arg2;
public Object obj;
Handler target;
private static Message sPool;
我们通常调用的是如下方法
代码中是handler.obtainMessage();
查看handler源码,obtainMessage()方法
public final Message obtainMessage()
{
return Message.obtain(this);
}
然后再跟踪,查看Message的obtain(Handler handler)方法如下
public static Message obtain(Message orig) {
Message m = obtain();
m.what = orig.what;
m.arg1 = orig.arg1;
m.arg2 = orig.arg2;
m.obj = orig.obj;
m.replyTo = orig.replyTo;
if (orig.data != null) {
m.data = new Bundle(orig.data);
}
m.target = orig.target;
m.callback = orig.callback;
return m;
}
Message方法中
public void sendToTarget() {
target.sendMessage(this);// this Message类型
}
调用的是
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
sendMessageDelayed调用的是
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
接下来讲Looper
Looper被设计用来使一个普通线程变成Looper线程。所谓Looper线程就是循环工作的线程。在程序开发中(尤其是GUI开发中),我们经常会需要一个线程不断循环,一旦有新任务则执行,执行完继续等待下一个任务,这就是Looper线程。
final MessageQueue mQueue;
Thread mThread;
private Printer mLogging = null;
private static Looper mMainLooper = null;
private static final ThreadLocal sThreadLocal = new ThreadLocal();
(ThreadLocal 实现了线程存储,每一个线程都有自己独立的存储,所有的线程都共享ThreadLocal,但是每一个线程都有自己单独的values,并且每一个线程修改自己的 values 并不影响其它线程的values,values存的是线程的属性,类似活的线程数量,死的线程数量,大小等等)ThreadLocal 类中有个Values私有类
ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。
Looper中的prepare方法
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
set的就是values的变量。
prepare()背后的工作方式一目了然,其核心就是将looper对象定义为ThreadLocal
private Looper() {
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}
Message的队列,通过looper循环message,message并不是直接加到messagequeue里面,而是通过handle加入的,可以通过Looper.myQueue()检索当前线程的MessageQueue
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
到此为止,你应该对Looper有了基本的了解,总结几点:
1.每个线程有且最多只能有一个Looper对象,它是一个ThreadLocal
2.Looper内部有一个消息队列,loop()方法调用后线程开始不断从队列中取出消息执行
3.Looper使一个线程变成Looper线程。
接下来讲Handler
handler扮演了往MQ上添加消息和处理消息的角色(只处理由自己发出的消息),即通知MQ它要执行一个任务(sendMessage),并在loop到自己的时候执行该任务(handleMessage),
里面有个接口
public interface Callback {
public boolean handleMessage(Message msg);
}
Handler中的常量
final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
IMessenger mMessenger;
Handler构造方法
public Handler(Looper looper) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = null;
}
public final Message obtainMessage()
{
return Message.obtain(this);
}
就是我们刚才的message的方法
handle的post方法,给messagequeue发送消息
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis); //该方法主要的任务就是把Message对象添加到MessageQueue中然后唤醒该线程
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
现在有疑问了,Message sendMessageDelayed 和handle的sendMessageDelayed两个方法有什么区别?
private final Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
接下来我们看一下HandleThread这个类
HandlerThread 继承Thread
三个参数
private int mPriority; 优先级
private int mTid = -1; 线程ID
private Looper mLooper; 当前Looper
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT; 默认为0 ,最大的值为19,表示不想执行该线程 -19-19
}
将当前优先级设置为默认的0
HandlerThread完美地解决了myLooper可能为空的问题
//线程1调用getLooper来获得新线程的Looper
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait(); //如果新线程还未创建Looper,则等待
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
//线程2
public void run() {
mTid = Process.myTid(); //获取当前线程ID
Looper.prepare(); //创建这个线程上的Looper
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll(); //通知取Looper的线程1,此时Looper已经创建好了
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
本文深入解析Android中的消息处理机制,包括Looper、Handler和Message的核心作用及工作原理。介绍了Message的参数与构造方法,Looper如何创建并维持消息队列,以及Handler如何发送与处理消息。
174

被折叠的 条评论
为什么被折叠?



