先分析完Message,MessageQueue源码
/**
* 获取Message的最好办法是调用Message.obtain()或Handler.obtainMessage()方法
* 这将会从message pool中获取,避免硬创建导致过大的开销。
*/
public final class Message implements Parcelable {
public int what;
public int arg1;
public int arg2;
public Object obj;
/*package*/ int flags;//还可以用这个属性存放参数?
/*package*/ long when;//还可以用这个属性存放参数?
/*package*/ Bundle data;//还可以用这个属性存放参数?
/*package*/ Handler target;//指定其处理场所,即宿主handler
/*package*/ Runnable callback;//message可以包含回调
// sometimes we store linked lists of these things
// next?message在messageQueue中是链式存储?
/*package*/ Message next;
private static final Object sPoolSync = new Object();//对象锁
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;//message pool最大数量50个
private static boolean gCheckRecycle = true;
/**
* 从全局池中返回一个新的消息实例。使我们能够避免在许多情况下分配新的对象.
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
/**
* 从消息池中获取一个message,设置orig的全部属性,浅克隆
*/
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;
m.sendingUid = orig.sendingUid;
if (orig.data != null) {
m.data = new Bundle(orig.data);
}
m.target = orig.target;
m.callback = orig.callback;
return m;
}
/**
* 获取message,指定target为h
*/
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
/**
* 获取message,指定特定的handler和callback
*/
public static Message obtain(Handler h, Runnable callback) {
Message m = obtain();
m.target = h;
m.callback = callback;
return m;
}
/**
* 将消息实例回收返回到全局消息池.
* 在调用此函数后,你不能触摸这个消息,因为它已被释放了。
* 这是回收的消息,目前正在排队或是在被传递到处理过程中
*/
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
/**
* 回收一个message,放到消息池中
*/
void recycleUnchecked() {
// 清空所有的属性值
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
/**浅拷贝参数message o到当前的message对象中,
* 但不拷贝linked list、timestamptarget、callback等属性的值。
*/
public void copyFrom(Message o) {
this.flags = o.flags & ~FLAGS_TO_CLEAR_ON_COPY_FROM;
this.what = o.what;
this.arg1 = o.arg1;
this.arg2 = o.arg2;
this.obj = o.obj;
this.replyTo = o.replyTo;
this.sendingUid = o.sendingUid;
if (o.data != null) {
this.data = (Bundle) o.data.clone();
} else {
this.data = null;
}
}
/**
* 设置一个任意数据的bundle数据包。如果没有复杂的数据需要传递,
* 你可以使用what,arg1,arg2,obj等的开销的属性传递。
*/
public void setData(Bundle data) {
this.data = data;
}
/**
* 发送消息到你指定的handler的handleMessage()实现方法中执行,
* 如果没有指定message的target属性,则会抛异常
*/
public void sendToTarget() {
target.sendMessage(this);
}
/**
* 构造方法,不推荐使用,优先Message.obtain()方法.
*/
public Message() {
}
//...
}
总结:
1、Message就是数据对象,类似于java里面的bean。
2、创建方式很多,可以浅克隆,可以调用无参构造方法,可以obtain等,obtain是最推荐的,效率高。
3、Message有what、arg1、arg2、obj等属性存储普通数据,复杂的可以使用Bundle方式存储传递。
4、Message有个next属性,类型也是Message类型的,你猜猜是什么?看完下文你就会懂的。
下面看看MessageQueue部分源码:
/**
* 这是个低级别的消息队列类,由looper持有以及消息分发。
* message不能直接的添加到这个队列中,而是通过handler对象关联的looper处理的。
* 你可以通过Looper.myQueue()获取当前线程的消息队列引用。
*/
public final class MessageQueue {
// message queue是否可以退出
private final boolean mQuitAllowed;
/**
* MessageQueue中的message都存放在mMessages中,这只是个链表头。
* 因为Message中有Message类型的next属性。回头看看Message源码
*/
Message mMessages;
//此方法是messageQueue最核心的方法,handler.sendMessageXXXXXX()等方法最终调用的都是这个方法,
//即经过一系列的处理,把message添加到messageQueue中
boolean enqueueMessage(Message msg, long when) {
//...
synchronized (this) {
//...
msg.markInUse();
msg.when = when;
Message p = mMessages;//把链表头赋给p
boolean needWake;
if (p == null || when == 0 || when < p.when) {
//如果链表头为null,或者新的message是when为0,或者新message的when在链表中靠前
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
/**
* 插入队列的中间。通常情况下,我们不需要唤醒事件队列,
* 除非队列头上有一个障碍,消息是队列中最早的异步消息。
*/
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
//循环迭代,找到新message的when合适的位置
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
//调用底层,唤醒队列
nativeWake(mPtr);
}
}
return true;
}
}
MessageQueue这个类我们平常很少接触到,但里面有一个重点需要了解,就是上面这个方法。
通过这个方法,handler把message添加到消息队列中。这些消息有即时的(0延时),有延时的。这些message在消息队列中是怎么存放的呢?
when < p.when
新message的when与链表中某个message的when对比,时间小的放在前面。明白了吧?MessageQueue依据延时的长短,从小到大排序排序。
下面看handler用法demo:
方法一:
/**
* handler最普通的用法
*
* @author duke
*
*/
public class MainActivity extends Activity {
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
toast(String.valueOf(msg.obj));
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void testHandler(View view) {
new Thread() {
public void run() {
mHandler.obtainMessage(200, "技术也是世界的,我们一起分享").sendToTarget();
};
}.start();
}
public void toast(String msg) {
Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}
方法二:
/**
* handler第二种用法
* 注意:在oncreate、onstart、onresume期间没有getMainLooper(),
* 关于在子线程中创建handler,参考:<a target=_blank href="http://blog.csdn.net/fesdgasdgasdg/article/details/52081773" target="_blank">http://blog.csdn.net/fesdgasdgasdg/article/details/52081773</a>
* 也可以不传递looper,handler或自己获取当前线程的looper。
* 此种方法没有实现handler的handleMessage方法
* @author duke
*
*/
public class MainActivity2 extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
private Handler mHandler;
public void testHandler(View view) {
mHandler = new Handler(getMainLooper());
new Thread() {
public void run() {
mHandler.post(new Runnable() {
@Override
public void run() {
toast("技术也是世界的,我们一起分享2");
}
});
};
}.start();
}
public void toast(String msg) {
Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}
方法三:
/**
* handler最普通的用法
* new一个Callback,让他来帮助handler处理message
* @author duke
*
*/
public class MainActivity3 extends Activity {
private Handler mHandler = new Handler(new Callback() {
@Override
public boolean handleMessage(Message msg) {
toast(String.valueOf(msg.obj));
//注意这儿返回true与false的区别
return true;
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void testHandler(View view) {
new Thread() {
public void run() {
mHandler.obtainMessage(200, "技术也是世界的,我们一起分享3").sendToTarget();
};
}.start();
}
public void toast(String msg) {
Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}
方法四:
/**
* handler最普通的用法
* new一个callback,同时实现handler的handleMessage方法,同时处理消息
* @author duke
*
*/
public class MainActivity4 extends Activity {
private Handler mHandler = new Handler(new Callback() {
@Override
public boolean handleMessage(Message msg) {
toast(String.valueOf(msg.obj));
//注意这儿返回true与false的区别
return false;
}
}){
@Override
public void handleMessage(Message msg){
//上面返回false,这儿同时也能处理消息
toast(String.valueOf(msg.obj));
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void testHandler(View view) {
new Thread() {
public void run() {
mHandler.obtainMessage(200, "技术也是世界的,我们一起分享4").sendToTarget();
};
}.start();
}
public void toast(String msg) {
Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}
方法五:
/**
* handler最普通的用法
* message中包含一个callback
* @author duke
*
*/
public class MainActivity5 extends Activity {
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main5);
}
public void testHandler(View view) {
new Thread() {
public void run() {
Message msg = Message.obtain(mHandler, new Runnable() {
@Override
public void run() {
toast("技术也是世界的,我们一起分享5");
}
});
mHandler.sendMessage(msg);
};
}.start();
}
public void toast(String msg) {
Toast toast = Toast.makeText(this, msg, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
}
是不是又看到了不少新鲜用法?
完了,Android多线程消息处理机制共四个章节,几乎都介绍完了。个人感觉介绍的很完整,相对于新手来说略有深度。