Android 消息机制之初识Handler [ 六 ]
前几章分解学习了 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 个构造函数, 可以发现其实构造函数的本质都是给下面四个本地变量赋值
mLoopermQueuemCallbackmAsynchronous
构造函数总结
- 如果
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 对消息的发送进行分析和学习.