android的handler是接口吗,Android——Handler

一、作用

轻松地将一个任务切换到 Handler 所在线程去执行。可用于发送消息和处理消息。

二、概念

0. Android 消息机制及源码分析

Handler

用于发送和处理消息。

一个线程中可有多个 Handler。

MessageQueue

消息队列,用于存放通过 Handler 发送的消息,等待被处理。

Looper 中维护一个 MessageQueue,一个线程只有一个 MessageQueue

Looper

Looper 是 MessageQueue 的管家,调用Looper.loop()方法后,就会进入到无限循环中,每当发现 MessageQueue 中存在一条消息,就将他取出,并传递给 Handler 处理。

每个线程只能有一个 Looper,Looper 保存在 ThreadLocal 中。主线程已经创建了 Looper 不需要再手动创建,其他线程的 Looper 需手动创建。

1. 发送消息 API

/**

* 将runnable添加到消息队列中, runnable 将在该Handler绑定的thread运行

*

* @param r

* @return

*/

public final boolean post(Runnable r) {

return sendMessageDelayed(getPostMessage(r), 0);

}

/**

* 将runnable添加到消息队列中,在指定时间(uptimeMillis)运行, runnable 将被该Handler绑定的thread运行

*

* @param r

* @param uptimeMillis @return:true:当runnable被正确添加到消息队列中;false:通常是由于处理消息队列的Looper正在退出。

* 注意:返回值为true,不代表runnable会被执行(例如:在消息被执行之前Looper退出了,那么该消息将被dropped丢弃)

*/

public final boolean postAtTime(Runnable r, long uptimeMillis) {

return sendMessageAtTime(getPostMessage(r), uptimeMillis);

}

/**

* 将runnable添加到消息队列中,在指定时间(uptimeMillis)运行,

*

* @param r

* @param token

* @param uptimeMillis

* @return

*/

public final boolean postAtTime(Runnable r, Object token, long uptimeMillis) {

return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);

}

/**

* 将runnable添加到消息队列,在指定时间后执行

*

* @param r

* @param delayMillis

* @return

*/

public final boolean postDelayed(Runnable r, long delayMillis) {

return sendMessageDelayed(getPostMessage(r), delayMillis);

}

/**

* 这个方法在极特殊的情况下才调用,可能导致side-effects

*

* @param r

* @return

*/

public final boolean postAtFrontOfQueue(Runnable r) {

return sendMessageAtFrontOfQueue(getPostMessage(r));

}

(2)send 的一系列方法

public final boolean sendMessage(Message msg) {

return sendMessageDelayed(msg, 0);

}

public final boolean sendEmptyMessage(int what) {

return sendEmptyMessageDelayed(what, 0);

}

public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {

Message msg = Message.obtain();

msg.what = what;

return sendMessageDelayed(msg, delayMillis);

}

public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {

Message msg = Message.obtain();

msg.what = what;

return sendMessageAtTime(msg, uptimeMillis);

}

public final boolean sendMessageDelayed(Message msg, long delayMillis) {

if (delayMillis < 0) {

delayMillis = 0;

}

return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);

}

public boolean sendMessageAtTime(Message msg, long uptimeMillis) {

MessageQueue queue = mQueue;

if (queue == null) {

RuntimeException e = new RuntimeException(

this + " sendMessageAtTime() called with no mQueue");

Log.w("Looper", e.getMessage(), e);

return false;

}

return enqueueMessage(queue, msg, uptimeMillis);

}

public final boolean sendMessageAtFrontOfQueue(Message msg) {

MessageQueue queue = mQueue;

if (queue == null) {

RuntimeException e = new RuntimeException(

this + " sendMessageAtTime() called with no mQueue");

Log.w("Looper", e.getMessage(), e);

return false;

}

return enqueueMessage(queue, msg, 0);

}

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

msg.target = this;

if (mAsynchronous) {

msg.setAsynchronous(true);

}

return queue.enqueueMessage(msg, uptimeMillis);

}

2. 移除消息

????

/**

* Remove any pending posts of Runnable r that are in the message queue.

*/

public final void removeCallbacks(Runnable r) {

mQueue.removeMessages(this, r, null);

}

/**

* Remove any pending posts of Runnable r with Object

* token that are in the message queue. If token is null,

* all callbacks will be removed.

*/

public final void removeCallbacks(Runnable r, Object token) {

mQueue.removeMessages(this, r, token);

}

/**

* Remove any pending posts of messages with code 'what' that are in the

* message queue.

*/

public final void removeMessages(int what) {

mQueue.removeMessages(this, what, null);

}

/**

* Remove any pending posts of messages with code 'what' and whose obj is

* 'object' that are in the message queue. If object is null,

* all messages will be removed.

*/

public final void removeMessages(int what, Object object) {

mQueue.removeMessages(this, what, object);

}

/**

* Remove any pending posts of callbacks and sent messages whose

* obj is token. If token is null,

* all callbacks and messages will be removed.

*/

public final void removeCallbacksAndMessages(Object token) {

mQueue.removeCallbacksAndMessages(this, token);

}

三、重点了解

1. Q:为什么在没有 Looper 的线程中创建 Handler 会引起异常

Handler 的构造函数

public Handler() {

this(null, false);

}

public Handler(Callback callback) {

this(callback, false);

}

public Handler(Looper looper) {

this(looper, null, false);

}

public Handler(Looper looper, Callback callback) {

this(looper, callback, false);

}

public Handler(boolean async) {

this(null, async);

}

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 that has not called Looper.prepare()");

}

mQueue = mLooper.mQueue;

mCallback = callback;

mAsynchronous = async;

}

/**

* 异步消息表示不需要相对于同步消息进行全局排序的中断或事件

*

* Handler默认是同步的,除非通过参数async明确指定它是异步的

* @param looper:使用提供的 Looper 而不是默认的Looper,必须不为空

* @param callback:使用提供的callback处理消息,可以为null

* @param async:

*/

public Handler(Looper looper, Callback callback, boolean async) {

mLooper = looper;

mQueue = looper.mQueue;

mCallback = callback;

mAsynchronous = async;

}

通过2个参数的构造函数可知,如果当前线程没有 Looper 的话,就会抛出异常,这也就解释了在没有 Looper 的子线程创建 Handler 会引起异常。

2. Q:Handler 如何处理消息

对消息的处理最终会回调到 Handler 的dispatchMessage()中。

/**

* Handle system messages here.

*/

public void dispatchMessage(Message msg) {

if (msg.callback != null) {

handleCallback(msg);

} else {

if (mCallback != null) {

if (mCallback.handleMessage(msg)) {

return;

}

}

handleMessage(msg);

}

}

从源码可得,

若是通过post方式发送的消息(该方式发送消息时会传入Runnable实例)

则直接在 Handler 所在线程中调用Runnable的run()

private static void handleCallback(Message message) {

message.callback.run();

}

若是send方式发送的消息

检查mCallback是否为空,其中mCallback是个接口类型

/**

* 这是一个接口,可以在实例化 Handler 时使用。

* 好处:在日常开发中,创建 Handler 的常见方式是派生一个 Handler 子类并重写 handlerMessage()来处理具体的消息。

* 有了 Callback,为我们创建 Handler 提供了另外一种可用方式,使得我们不想派生子类时,可以通过 Callback 实现。

*

* @param msg A {@link android.os.Message Message} object

* @return True if no further handling is desired

*/

public interface Callback {

public boolean handleMessage(Message msg);

}

Handler 提供了带Callback的构造函数,mCallback即为构造函数中传入的。

/**

* 该构造函数将 Handler 和当前线程联系起来,Callback用于处理消息

*

* 如果当前线程没有 Looper,Handler 不可接收消息,并且会抛出异常

*

* @param callback The callback interface in which to handle messages, or null.

*/

public Handler(Callback callback) {

this(callback, false);

}

mCallback不为空:调用mCallback.handleMessage(msg)

mCallback为空:调用Handler::handleMessage(msg)(该方法由 Handler 派生的子类重写,以处理消息)。

3. 获取 Message 的2种方式的比较

0b8978753be1

2种方式

推荐使用Message.obtain():从全局消息池中返回一个新的消息实例,在多数情况下可以避免分配新对象。

三、使用

1. Handler 的创建

创建子类继承Handler,重写handleMessage()

// 在主线程中创建实例

private MyHandler mHandler = new MyHandler();

private static class MyHandler extends Handler {

@Override

public void handleMessage(@NonNull Message msg) {

super.handleMessage(msg);

switch (msg.what) {

case 1:

break;

default:

break;

}

}

}

匿名内部类

// 在主线程中创建

private Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

System.out.println(msg.what);

}

};

2.发送消息

post

post 方法将一个 Runnable 投递到 Handler 内部的 Looper 中去处理,

mHandler.post(new Runnable() {

@Override

public void run() {

... // 需在目标线程中执行的操作(如:更新UI)

}

});

send

// 实例化消息对象

Message msg = Message.obtain();

msg.what = 1; // 消息标识

msg.obj = "AA"; // 消息内容存放

mHandler.sendMessage(msg);

参考文献

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值