Android Handler机制——Handler

Android Handler机制——Handler

  Handler机制是一个典型的异步环境下的生产者-消费者模型,Handler为生产者,Looper为消费者,Message为产物,MessageQueue则是暂存产物的仓库(缓冲区)。

一、构造

public Handler();
public Handler(@Nullable Callback callback);
public Handler(@NonNull Looper looper);
public Handler(@NonNull Looper looper, @Nullable Callback callback);
public Handler(boolean async);
public Handler(@Nullable Callback callback, boolean async);
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async);

  Handler有多个构造函数,但实际初始化都是在最后两个构造中实现。

final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;
final boolean mAsynchronous;

public Handler(@Nullable Callback callback, boolean async) {
	//用于检测检测匿名、本地或成员类扩展这个 Handler 类并且不是静态的。 这类类可能会造成泄漏。
	//一般不启用
	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;
}

public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
	mLooper = looper;
	mQueue = looper.mQueue;
	mCallback = callback;
	mAsynchronous = async;
}

  可见Handler的构造函数只做一件事——对mLooper、mQueue、mCallbac、mAsynchronous四个成员变量赋值。
  这两个构造函数的主要区别便是获取mLooper的手段不同。若构造传参没有传入looper,则mLooper通过Looper.myLooper()方法获取Looper,该方法会获取当前运行线程的Looper。mQueue则是从Looper中获取的MessageQueue,MessageQueue由Looper负责实例化。

  类关系如下图所示。
在这里插入图片描述

二、事件投递

  Handler作为异步处理机制。MessageQueue为装载事件(消息)的容器,Looper为的线程驱动主体。Handler直译为处理器,实际只是整个机制向外暴露的接口。它有多个接口可以实现事件的投递。

public final boolean post(@NonNull Runnable r);
public final boolean postAtTime(@NonNull Runnable r, long uptimeMillis);
public final boolean postAtTime(@NonNull Runnable r, @Nullable Object token, long uptimeMillis);
public final boolean postDelayed(@NonNull Runnable r, long delayMillis);
public final boolean postDelayed(Runnable r, int what, long delayMillis);
public final boolean postDelayed(@NonNull Runnable r, @Nullable Object token, long delayMillis);
public final boolean postAtFrontOfQueue(@NonNull Runnable r);
public final boolean sendMessage(@NonNull Message msg);
public final boolean sendEmptyMessage(int what);
public final boolean sendEmptyMessageDelayed(int what, long delayMillis);
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis);
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis);
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis);
public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg);
public final boolean executeOrSendMessage(@NonNull Message msg);

  暴露出来的接口很多,但最终都会调用到sendMessageAtTime或者sendMessageAtFrontOfQueue,而这两个方法最终会调到enqueueMessage方法中。

public boolean sendMessageAtTime(@NonNull 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(@NonNull 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(@NonNull MessageQueue queue, @NonNull Message msg,
		long uptimeMillis) {
	//Message绑定Handler
	msg.target = this;
	//该变量在Handler机制跨进程使用时用到,该功能未对APP端开放
	msg.workSourceUid = ThreadLocalWorkSource.getUid();	
	//根据mAsynchronous判断是否同步执行
	if (mAsynchronous) {
		msg.setAsynchronous(true);
	}
	return queue.enqueueMessage(msg, uptimeMillis);
}

  sendMessageAtTime和sendMessageAtFrontOfQueue唯一区别便是时间参数。MessageQueue中维护了一个链表用于存储Message,该链表会根据enqueueMessage方法中传入的时间对Message进行排序,时间小的先处理。sendMessageAtFrontOfQueue顾名思义,其传入时间为0,进入MessageQueue后必然会排在最前面,会最优先处理对应的Message。

  enqueueMessage主要职责便是将Message塞入MessageQueue中。值得注意的是,Message会在该方法中与Handler绑定。而msg.workSourceUid用于存储Message发送方的Uid,这个变量会在Handler用于跨进程通信时用到,但APP端并没有暴露Handler跨进程相关的功能,因此并不需要过多关注它。

三、事件处理器

  Handler机制有多个事件处理方式。

  1.重载Handler的handleMessage方法。

  2.传入Message时设置Message的callback成员变量。

  3.设置Handler的mCallback成员变量。

  从Handler处理事件的方法来看:

public void dispatchMessage(@NonNull Message msg) {
	if (msg.callback != null) {
		handleCallback(msg);
	} else {
		if (mCallback != null) {
			if (mCallback.handleMessage(msg)) {
				return;
			}
		}
		handleMessage(msg);
	}
}

private static void handleCallback(Message message) {
	message.callback.run();
}

public void handleMessage(@NonNull Message msg) {
}

  在looper处理事件时,便会调用dispatchMessage方法。从代码可以看出,三种方式的优先级分别是:1.message的callback。2.Handler的mCallback成员变量以及handleMessage方法。

  值得注意的是,当message有callback成员变量是便不会执行后续的处理方法,且当mCallback的返回值未true时,也不会再执行Handler的handleMessage方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值