Android 消息机制深入源码分析 [ 一 ]
Android 消息机制之 ThreadLocal 深入源码分析 [ 二 ]
Android 消息机制之 Looper 深入源码分析 [ 三 ]
Android 消息机制之 Message 与消息对象池的深入源码分析 [ 四 ]
Android 消息机制之 MessageQueue 深入源码分析 [ 五 ]
Android 消息机制之初识Handler [ 六 ]
Android 消息机制之 Handler 发送消息的深入源码分析 [ 七 ]
Android 消息机制之 MessageQueue.next() 消息取出的深入源码分析 [ 八 ]
Android 消息机制之消息的其他处理深入源码分析 [ 九 ]
Android 消息机制总结 [ 十 ]
前几章分解学习了 ThreadLocal
, Looper
, Message
, MessageQueue
等相关的知识, 本章节开始正式学习 Android 中消息机制的重中之重 Handler
. 那么让我们正式开始学习吧.
1. 什么是 Handler
- Handler 是一个可以通过关联一个消息队列来发送和处理消息, 发送或处理 Runnable 对象的一个处理程序.
- 每个 Handler 都关联一个单个的线程和消息队列. 当我们创建一个新的 Handler 的时候, 它就绑定到一个线程上或者线程上的消息队列, 从那个时候起, 这个 Handler 就将为这个消息队列提供消息或者 Runnable 对象处理消息队列释放出来的消息或者 Runnable 对象.
2. Handler 有什么用
- 安排消息和 Runnable 对象在未来执行.
- 将用户的一个动作放在不同的线程上执行.
3. 构造函数
Handler 的构造函数一共有七个, 六个是有参, 一个无参的, 所有的构造函数都为 public
- 1.public Handler()
- 2.public Handler(Callback callback)
- 3.public Handler(Looper looper)
- 4.public Handler(Looper looper, Callback callback)
- 5.public Handler(boolean async)
- 6.public Handler(Callback callback, boolean async)
- 7.public Handler(Looper looper, Callback callback, boolean async)
这七个构造函数, 又将分为两类. 分别为两个参数的 1. 2. 5. 6 和 三个参数的 3. 4. 7. 接下来将对这个构造函数逐个分析学习.
1. public Handler()
public Handler() {
this(null, false);
}
- 解析:
内部调用的构造 6. 只不过第一个传入的的为
null
, 第二个传入的为false
.
2. public Handler(Callback callback)
public Handler(Callback callback) {
this(callback, false);
}
- 解析:
内部调用的也是构造 6.第一个传入参数为
callback
回调, 第二个依然为false
, 回调Callback
会放在后面分析. 目前暂时先知道是一个回调就行了.
5. public Handler(boolean async)
public Handler(boolean async) {
this(null, async);
}
- 解析:
内部调用的也是构造 ⑥,第一个传入
null
,第二个参数为boolean
类型的async
以上是一个无参和两个有参的, 1. 2. 5. 但是他们归根结底调用的都是构造函数 6. 所以现在一起看下构造函数 6.
6. public Handler(Callback callback, boolean async)
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class extends Handler> klass = getClass();
//如果是匿名类, 内部类, 局部类,且没有声明 static,则存在内存泄露风险,所以打印日志进行提醒
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());
}
}
//获得当前线程的 Looper
mLooper = Looper.myLooper();
//如果当前线程没有 Looper,则说明没有还没有调用 Looper.loop,抛异常
if (mLooper == null) {
throw new RuntimeException("Can't create handler inside thread " + Thread.currentThread() + " that has not called Looper.prepare()");
}
//把 Looper 的 Queue 赋值给 Handler 的 mQueue
mQueue = mLooper.mQueue;
//赋值给 callback
mCallback = callback;
//赋值 mAsynchronous
mAsynchronous = async;
}
- 解析:
使用当前线程的
Looper
, 使用传入的回调, 并设置这个Handler
是否是异步的.
除非在创建Handler
的时候指定为异步的, 否则默认的Handler
默认都是同步的.
异步消息相对于同步消息而言, 表示消息不会受到终端或者事件的影响其全局顺序, 异步消息是不会受到MessageQueue.enqueueSyncBarrier(long)
的同步障栅影响
Handler
默认采用的是当前线程ThreadLocal
中的Looper
对象, 只要执行了Looper.prepare()
方法, 就可以获取有效的Looper
对象. 同时在 消息机制的第三篇 Looper 篇 的时候也说了Looper
的构造函数关联了MessageQueue
和Thread
.
所以在同一个线程里面(已经调用了Looper.prepare()
),Handler
中的MessageQueue
与Looper
中的MessageQueue
指向的是同一个消息队列.
下面是三个参数的构造函数.
3. public Handler(Looper looper)
public Handler(Looper looper) {
this(looper, null, false);
}
- 解析
内部调用了构造 7. 传入参数不同.
4. public Handler(Looper looper, Callback callback)
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
不难发现, 上面两个默认调用的都是三个参数的构造函数, 都是非异步的.
7. public Handler(Looper looper, Callback callback, boolean async)
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
- 解析:
不使用默认的
Looper
, 而使用由第一个参数传入的Looper
对象.
综合 7 个构造函数, 可以发现其实构造函数的本质都是给下面四个本地变量赋值
mLooper
mQueue
mCallback
mAsynchronous
构造函数总结
- 如果
Handler
的构造中没有给Looper
, 则使用默认的Looper
, 也就是在当前线程ThreadLocal
中关联的Looper
.
通过ThreadLocal.Looper.mQueue
来给Handler.mQueue
赋值.
实现Handler, Looper, MessageQueue
三者的绑定. - 通过构造函数来设置
Callback
的回调接口, 不设置则为null
. - 通过
mAsynchronous
来控制是同步还是异步, 而mAsynchronous
的默认值为false
.mAsynchronous
可以通过构造函数来设置.
最后来说一下回调接口, 也就是 Handler.Callback 接口
public interface Callback {
public boolean handleMessage(Message msg);
}
- 官方翻译:
通过设置这个接口去处理消息,就不需要再定义一个Handler的子类. 在调用 handler 构造函数的时候, 可直接使用这个接口. 返回值为
true
表示不继续向下分发, 返回false
还会向下分发, 会调用Handler.handleMessage()
方法. 在下一章Handler
消息分发中会分析到.
(注意: 这个 handleMessage 可不是我们经常使用的那个. 这个是 callback 的 handleMessage.
我们经常使用的那个handleMessage
是Handler
自带的一个方法. 也叫handleMessage
)
- 理解
其实
Callback
可以和Handelr.handleMessage
一起使用, 我尝试了一下, 可以产生类似过滤器的效果. 首先创建一个类继承自Handler
, 重写void handleMessage
方法. 处理一些通用的消息. 然后在使用的Activity
中, 创建Handler
的时候, 使用我们自己定义的Handelr
, 其中参数传入new Handler.Callback()
, 并实现boolean handleMessage
. 在其中做一些处理. 示例如下.
class myHandler extends Handler{
public myHandler(@Nullable Callback callback) {
super(callback);
}
@Override
public void handleMessage(@NonNull Message msg) {
Log.e("myHandler","___what=" + msg.what);
super.handleMessage(msg);
}
}
public class MainActivity extends AppCompatActivity {
Button button1,button2;
private static myHandler handler = new myHandler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
if(msg.what == 100){
Log.e("myHandler","___Callback=" + msg.what);
return true;
}
return false;
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = findViewById(R.id.button1);
button2 = findViewById(R.id.button2);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message message = Message.obtain();
message.what = 100;
handler.sendMessage(message);
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message message = Message.obtain();
message.what = 1000;
handler.sendMessage(message);
}
});
}
}
- 点击
button1
, 打印的是___Callback=100
, 拦截了消息 - 点击
button2
, 打印的是___what=1000
, 接收到了消息.
这是我对 Callback.handleMessage
的简单理解. 平时我们估计都不会经常用到这个 Callback
, 估计一般用到的都是无参的 Handler
.
本章对 Handler
的初识就到这里就结束了, 下一章会开始 Handler
对消息的发送进行分析和学习.