此文一起来看下Handler的部分源码,不用怕很简单,有英文的地方我都翻译了。
把里面相关的方法过一眼,你瞬间会明白很多。高手就不用看了,去过你的荣华富贵花天酒地。
我一致认为,想学好某一技术,首先是了解原理和熟练使用,其次是钻研其源码,看他是怎么做的。
万万不可随便在网上搜篇文章做一个demo完事,你可知有多少文章讲多么肤浅和曲解?
曾记得以前看过一个视频教程,那讲师说:“有两个队列,一个是messageQueue,一个是threadQueue”
他把runnable都当线程理解了。
1、handler可以在构造的时候传递callback,以替换handleMessage方法处理消息。
2、在构造handler的时候,可以不传递looper,默认会取当前线程的looper。如果娶不到就挂了。也可以传递looper给他。
3、handler分发message时,先判断msg的callback是否有值,有则调用runnable的run方法,不是启动线程!否则判断handler的callback是否有值,有则让其处理消息。如果处理完成后return true,则handler的handleMessage(msg)不执行了,否则继续执行。
4、获取message,或许可以new,暂时还没分析。源码已经指出可以用obtain的方式从message pool中获取,效率高。
5、handler可以发及时或延时消息,可以移除部分或者全部的待处理消息。
由于篇幅太长,此文就只聊这么多,下文总结handler用法和讲解message、messageQueue。
把里面相关的方法过一眼,你瞬间会明白很多。高手就不用看了,去过你的荣华富贵花天酒地。
我一致认为,想学好某一技术,首先是了解原理和熟练使用,其次是钻研其源码,看他是怎么做的。
万万不可随便在网上搜篇文章做一个demo完事,你可知有多少文章讲多么肤浅和曲解?
曾记得以前看过一个视频教程,那讲师说:“有两个队列,一个是messageQueue,一个是threadQueue”
他把runnable都当线程理解了。
任何技术,官方文档和源码是最直接的证据和学习资料。源码撸起:
/**
* 一个handler实例可以用来发送和处理message,也可以与一个runnable对象关联.
* 每一个handler只可以与一个looper关联,一个线程最多只能有一个looper,
* 一个looper内置一个唯一的messageQueue。在同一个线程中,你可以再创建一个handler,
* 与同一个looper和messageQueue关联。若多个handler关联同一个looper,则发送的message都会
* 装载同一个messageQueue里面,由同一个looper管理。looper抽取出message后,会让message找
* 的妈妈。message是谁发送的,就有谁的handleMessage()方法处理。因为message.target = handler,
* message持有妈妈的电话号码
*/
public class Handler {
//Handler的成员变量
final MessageQueue mQueue;//引用所关联的looper的messageQueue
final Looper mLooper;//所关联的looper
final Callback mCallback;//handler有callback属性
final boolean mAsynchronous;//是否异步
IMessenger mMessenger;
//...
/**
* 在构建Handler实例的时候提供一个CallBack接口,避免实现你自己的handler子类
* @param msg 一个message对象
* @return True 如果没必要传递,就返回true消耗处理
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
/**
* 子类必须实现这个方法,来接收和处理消息
*/
public void handleMessage(Message msg) {
}
/**
* 在这里处理系统消息分发
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//mssage里面有CallBack?稍后分析
handleCallback(msg);
} else {
if (mCallback != null) {
//mCallback是Handler的回调吗?就是上面提到的接口?
if (mCallback.handleMessage(msg)) {
return;
}
}
//这个就是上面提到的接收和处理消息的方法吗?
handleMessage(msg);
}
}
/**
* 无参数的构造方法创建handler对象,默认关联当前线程的looper。
* 如果这个线程没有looper, 这个handler将不能接收和发送message,
* 且抛出异常。
* 明白了为什么在activity创建handler不需要关联looper了吧?因为他自己关联。
* 在looper专题1章节讲解到的,Looper.prepare()之后才创建的handler,知道为什么了吧?
* 我在new handler的时候传递了looper?看下一个构造方法吧。
*/
public Handler() {
this(null, false);
}
/**
* 使用提供的looper对象替换handler中默认的looper,
* 以免因为默认的looper为null而导致程序异常。
* @param looper 这个looper不能为空
*/
public Handler(Looper looper) {
this(looper, null, false);
}
/**
* 构造一个关联当前默认线程的looper的handler对象,
* 同时携带一个可以为你处理message的回调接口。不用handleMessage(Message msg)方法了?!!
* 如果当前线程没有looper,那就等着作死吧
* @param callback 你可以用这个回调类处理message,你也可以不传递,
* 实现handleMessage(Message msg)方法
*/
public Handler(Callback callback) {
this(callback, false);
}
/**
* 同时提供looper和CallBack回调
*/
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
/**
* 使用默认线程的looper,同时设置处理程序是否应该是异步的
* handler默认是同步的,除非特别指定是异步的。
* 此构造函数是隐藏的,我们不可以调用
*/
public Handler(boolean async) {
this(null, async);
}
/**
* 使用当前默认的looper,指定的CallBack,设置是否需要异步
* Handler默认是同步的,除非调用带有此项设置的构造器。
*
* 异步消息表示不需要全局排序就同步消息的中断或事件.
* 异步消息不受MessageQueue#enqueueSyncBarrier(long)方法同步阻拦.
*
* @hide 这是一个隐藏的构造方法
*/
public Handler(Callback callback, boolean async) {
//返回当前线程的looper,如果当前线程没有looper,则返回null
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//获取looper里面的消息队列,赋值给当前handler对象。有人说他这样很无耻
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
//这个构造方法不用多说,一看就懂
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
/**
* 返回一个表示指定消息的名称的字符串.
* 默认的实现将返回message的CallBack类名,
* 或者返回message的what属性值的16进制表示形式.
*/
public String getMessageName(Message message) {
if (message.callback != null) {
return message.callback.getClass().getName();
}
return "0x" + Integer.toHexString(message.what);
}
/**
* 从全局的message池中返回一个全新的message对象,比创建和分配新实例更有效
* 返回的message的target属性会设置为this,即待处理对象
* 如果你不想给message的target属性赋值,可以调用Message.obtain()方法,不传参数
*/
public final Message obtainMessage(){
return Message.obtain(this);
}
/**
* 与上面重载的方法的区别,obtain的同时设置了what属性
*/
public final Message obtainMessage(int what){
return Message.obtain(this, what);
}
/**
* 又设置了一个object属性,以满足message返回任意类型数据
*/
public final Message obtainMessage(int what, Object obj){
return Message.obtain(this, what, obj);
}
/**
* 参数全家福,到齐了。这些参数没有特定的含义,根据你的需要设置和使用
* @param what Value to assign to the returned Message.what field.
* @param arg1 Value to assign to the returned Message.arg1 field.
* @param arg2 Value to assign to the returned Message.arg2 field.
* @param obj Value to assign to the returned Message.obj field.
* @return A Message from the global message pool.
*/
public final Message obtainMessage(int what, int arg1, int arg2, Object obj){
return Message.obtain(this, what, arg1, arg2, obj);
}
/**
* 使runnable对象添加到消息队列.
* 这个runnable将会运行在handler所在的线程
* 如果runnable成功的添加到消息队列则返回true,否则失败。
* 如果返回false,通常是looper执行的消息循环退出了导致的
*/
public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
/**
* 添加runnable到消息队列中,让其在给定的延时后运行
*
* 如果runnable成功的添加到消息队列则返回true,否则失败。
* 如果返回false,通常是looper执行的消息循环退出了导致的
*
*/
public final boolean postAtTime(Runnable r, long uptimeMillis){
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
/**
* 发布一个message到一个实现了runnable的对象中.
* 通过消息队列的下一次迭代时执行该runnable.
* 这个runnable将会在handler所在的线程中执行.
* 这种方法只是在非常特殊的情况下使用。
* 它可以很容易地饿死消息队列,导致排序问题,或有其他意想不到的副作用。
*/
public final boolean postAtFrontOfQueue(Runnable r){
return sendMessageAtFrontOfQueue(getPostMessage(r));
}
/**
* 同步运行指定的任务
* 如果当前线程与handler所在的线程相同, 则立即执行;否则进入消息队列排队.
* </p><p>
* 这种方法是危险的!使用不当可能导致死锁.
* 当某些锁被占用或使用重新进入时不要调用此方法
*
* 这种方法有时是有用的,在后台线程必须同步等待完成一个任务,
* 必须在处理程序的线程上运行的情况下。然而,这个问题往往是糟糕的设计的一个症状。
* 考虑改进设计(如果可能),然后再使用该方法.
*
* 隐藏的方法
*/
public final boolean runWithScissors(final Runnable r, long timeout) {
if (r == null) {
throw new IllegalArgumentException("runnable must not be null");
}
if (timeout < 0) {
throw new IllegalArgumentException("timeout must be non-negative");
}
//如果handler与looper同一个线程中,则立即实行runnable的run方法。
if (Looper.myLooper() == mLooper) {
r.run();
return true;
}
//否则构造一个BlockingRunnable任务,在给定的时间后执行
BlockingRunnable br = new BlockingRunnable(r);
return br.postAndWait(this, timeout);
}
/**
* 移除消息队列中即将执行的runnable
*/
public final void removeCallbacks(Runnable r){
mQueue.removeMessages(this, r, null);
}
/**
* 移除消息队列中含有object类型的token的runnable任务
* 如果token为null,则移除所有的callbacks。
*/
public final void removeCallbacks(Runnable r, Object token){
mQueue.removeMessages(this, r, token);
}
/**
* 在当前时间之前,将一个消息推到消息队列的末尾
* message将会被发送者的handleMessage()方法收到。
*/
public final boolean sendMessage(Message msg){
return sendMessageDelayed(msg, 0);
}
/**
* 发送一个只包含what属性值的message.
*/
public final boolean sendEmptyMessage(int what){
return sendEmptyMessageDelayed(what, 0);
}
/**
* 发送一个只包含what属性值的message, 在给定的时间之后交付.
*/
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
/**
* 移除消息队列中waht属性值与给定值相等的message
*/
public final void removeMessages(int what) {
mQueue.removeMessages(this, what, null);
}
/**
* 移除消息队列中waht属性值与给定值相等且obj属性值与给定值相等的message。
* 如果object值为null,则移除全部message
*/
public final void removeMessages(int what, Object object) {
mQueue.removeMessages(this, what, object);
}
/**
* 删除任何即将发布的callbacks和obj属性值为token的messages。
* 如果token是null,所有的callbacks和message将被删除。
*/
public final void removeCallbacksAndMessages(Object token) {
mQueue.removeCallbacksAndMessages(this, token);
}
/**
* 检查消息队列中是否有what属性值为给定值的message.
*/
public final boolean hasMessages(int what) {
return mQueue.hasMessages(this, what, null);
}
/**
* 检查消息队列中是否有what、obj属性值为给定值的message.
*/
public final boolean hasMessages(int what, Object object) {
return mQueue.hasMessages(this, what, object);
}
/**
* 检查消息队列中是否存在含有callback的message
*
* @hide 隐藏的方法
*/
public final boolean hasCallbacks(Runnable r) {
return mQueue.hasMessages(this, r, null);
}
// 获取当前线程的looper
public final Looper getLooper() {
return mLooper;
}
/**
* 注意此方法,参数runnable放到哪儿了?
*
*/
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
/**
* token就是message对象的obj属性值
* message也有callback属性?
*/
private static Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain();
m.obj = token;
m.callback = r;
return m;
}
/**
* 调用message的callback对象的run方法。不是启动线程!!!!
*/
private static void handleCallback(Message message) {
message.callback.run();
}
//前面提到的BlockingRunnable内部类
private static final class BlockingRunnable implements Runnable {
private final Runnable mTask;
private boolean mDone;
public BlockingRunnable(Runnable task) {
mTask = task;
}
@Override
public void run() {
try {
mTask.run();
} finally {
synchronized (this) {
mDone = true;
notifyAll();
}
}
}
//...
}
}
1、handler可以在构造的时候传递callback,以替换handleMessage方法处理消息。
2、在构造handler的时候,可以不传递looper,默认会取当前线程的looper。如果娶不到就挂了。也可以传递looper给他。
3、handler分发message时,先判断msg的callback是否有值,有则调用runnable的run方法,不是启动线程!否则判断handler的callback是否有值,有则让其处理消息。如果处理完成后return true,则handler的handleMessage(msg)不执行了,否则继续执行。
4、获取message,或许可以new,暂时还没分析。源码已经指出可以用obtain的方式从message pool中获取,效率高。
5、handler可以发及时或延时消息,可以移除部分或者全部的待处理消息。
由于篇幅太长,此文就只聊这么多,下文总结handler用法和讲解message、messageQueue。