前言
Handler类定义在android/os/Handler.java文件中,做Android的同学,对Handler一定再熟悉不过……今天一起学习Handler对象的创建代码……
创建Handler对象,在Handler类中提供7个构造方法,其中3个构造方法可以直接使用,剩余的构造方法为hide修饰,无法直接使用
无参构造方法(常用)
public Handler() {
this(null, false);
}
这是最常用的一个构造方法,在它的方法体内部直接调用了重载的拥有两个参数的构造方法,并传入了一个null、一个false。
null值表示无需回调的Callback对象,false表示创建的Handler对象发送的是同步消息
两个参数的构造方法(hide修饰)
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
传入的第一个参数为Callback对象,表示用于回调的对象,第二个参数为boolean值,表示此Handler发送的消息类型,传入false值表示同步消息,传入true值表示异步消息……接待下来我们看下构造方法体中执行了哪些代码
1、检查潜在的内存泄漏
FIND_POTENTIAL_LEAKS为一个常量,它的固定值为false,说明检查内存泄漏的代码,只有在debug环境中才启用,看来Google大佬们也有预留的调试代码 ,怎么检测的内存泄漏?这里先不做分析,我们接下来看看业务逻辑
2、获取Looper对象,并开始持有
通过Looper的静态方法myLooper()获得Looper对象,并赋值给Handler对象持有的实例变量mLooper
3、检查获取Looper对象的结果
如果mLooper指向的是null,说明Looper的静态方法myLooper()没有获取到一个Looper对象,通过抛出RuntimeException异常对象,告知用户当前线程中没有创建Looper对象
4、获取Looper对象持有的MessageQueue对象
检查获取Looper对象通过后,接着将Looper对象持有的MessageQueue对象赋值给Handler对象持有的mQueue中,此时说明当前Handler对象开始持有Looper对象持有的MessageQueue对象
5、将传入的Callback对象保存起来
Handler对象持有的实例变量mCallback负责保存传入的Callback对象,每个Callback表示回调的对象
PS:Callback类是定义在Hander类的内部的一个静态内部interface,内部只有一个handleMessage(Message msg)抽象方法
public interface Callback {
public boolean handleMessage(Message msg);
}
6、将传入的消息类型保存起来
Handler对象持有的实例变量mAsynchronous负责保存传入的boolean值,此boolean值表示Handler对象发送消息的类型,消息类型有两种,一个是同步消息、另一个是异步消息(注意:所有设置mAsynchronous状态的构造方法都是hide状态)
传入一个boolean值参数的构造方法(@hide修饰)
public Handler(boolean async) {
this(null, async);
}
同样在内部调用的是可传入一个Callback对象、一个boolean值参数的构造方法。传入的null表示无需指定Callback对象,传入的async表示Handler发送消息的类型
传入一个Callback对象的构造方法(常用)
public Handler(Callback callback) {
this(callback, false);
}
同样在构造方法的内部调用的是需要的是两个参数的构造方法
传入一个Looper对象的构造方法(常用)
public Handler(Looper looper) {
this(looper, null, false);
}
方法内部会调用了三个参数的构造方法,将传入的Looper对象直接传了进去,后面依次传入的Callback为null,消息类型标志位为false,说明创建的Handler发送的消息是同步消息
三个参数的构造方法(hide修饰)
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
1、保存传入的Looper对象
为Handler对象持有的mLooper赋值一个传入的Looper对象
2、保存Looper对象持有的MessageQueue对象
为Handler对象持有的mQueue赋值Looper对象持有的MessageQueue对象,每个Handler对象都会持有Looper对象持有的MessageQueue对象
3、保存传入的Callback对象
Handler对象持有的mCallback赋值为传入的Callback对象
4、保存发送消息的类型
Handler对象持有的mAsynchronous赋值为传入的标志位值async,该值表示该Handler发出的消息类型(true表示异步消息,false表示同步消息)
两个参数的构造方法
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
方法体内部直接调用了三个参数构造方法,传入的looper、callback直接传了进去、最后一个boolean值传入的是false,说明创建的是发送同步消息的Handler对象
总结
1、Handler对象持有一个Looper对象
2、Handler对象也持有了Looper对象持有的MessageQueue对象
3、Handler可持有一个Callback对象,该Callback表示回调的对象,可不传入
4、Handler对象持有一个mAsynchronous标志位,该标志位代表Handler发出的消息类型,true表示异步消息,false表示同步消息
5、Handler对象持有的mAsynchronous标志位,所有相关的构造方法都是hide修饰的,我们想创建异步消息的Handler对象,有两个办法:
第一、使用反射在运行时修改
第二、使用Message对象的setAsynchronous()方法可以设置消息类型(因为mAsynchronous标志位会传递给Message对象,由它来使用)
Handler的日常使用方式(自动发送消息,自己处理消息)