你在网上看了不少handler的原理,是否是有迷茫的地方,为何是那个样子的?java
老是听你们侃侃而谈,谈的内容仍是千篇一概,流程原理说的也是那么个回事,可是再往深问一点,又啥啥不会。。。android
若是你以为有必要深深的理解它,记住它,请给我一块儿看看它是如何实现的缓存
handler是android提供的一个能够在线程间传递消息的机制,主要涉及类有:Looper,MessageQueue,Message; 咱们先从消息对象来看源码吧bash
不只是一个数据类,还实现了Parcelable接口,并且也包含了一个单链表的数据结构,还经过对象池,实现了复用数据结构
public int what;
public int arg1;
public int arg2;
public Object obj;
public Messenger replyTo;
public int sendingUid = UID_NONE;
public int workSourceUid = UID_NONE;
int flags;
public long when;
Bundle data;
Handler target;
Runnable callback;
Message next;
复制代码
主要包含一下数据内容异步
对于跨进程使用,则主要涉及轻量级跨进程通讯Messenger机制,有兴趣的能够自行了解,这里暂时不介绍了ide
池是啥?简单理解:池是使用过对象进行缓存,须要使用对象时,从缓存拿实例,进行变量从新设置便可;好处就是减小对象的建立,减小内存剧烈波动oop
这里是池技术相关变量大数据
Message next;
public static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
private static boolean gCheckRecycle = true;
复制代码
gCheckRecycle变量这里不可直接操做能够经过反射来设置;其值改变方法被hide了并且这个方法只有在L版本一下,才会改变;另外池的复用主要是这个变量,为true表示已经使用过的对象ui
/** @hide */
public static void updateCheckRecycle(int targetSdkVersion) {
if (targetSdkVersion < Build.VERSION_CODES.LOLLIPOP) {
gCheckRecycle = false;
}
}
复制代码
池数据使用了单链表结构,先入后出的操做逻辑吗,sPool链表头;池中最大数据为50个,每次回收对象时,则重置对象的全部相关数据
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
void recycleUnchecked() {
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = UID_NONE;
workSourceUid = UID_NONE;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
复制代码
从链表的表头拿出数据
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0;
sPoolSize--;
return m;
}
}
return new Message();
}
复制代码
主要使用了队列进行消息的排队,也是单链表结构,按照时间递增排序;仍是用了原生方法进行等待,唤醒操做
是一个符合消费者模式的队列 相关变量
Message mMessages; // 消息队列对头
private boolean mQuitting; // 是否结束
private boolean mBlocked; // 是否被阻塞
复制代码
入队操做
入队前,先检查状态
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p;
prev.next = msg;
}
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
复制代码
入队过程
出队操做
出队操做是一个阻塞操做
Message next() {
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1;
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
nextPollTimeoutMillis = -1;
}
if (mQuitting) {
dispose();
return null;
}
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null;
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
pendingIdleHandlerCount = 0;
nextPollTimeoutMillis = 0;
}
}
复制代码
大体流程以下
原生对象映射java对象中,实际上是把地址java成员变量中,java方法经过把指针来操做原生对象
这里mPtr为原生对象地址
nativeWake方法
nativePollOnce方法
消息的发送,是有Handler发起的,消息的接收也是由handler来处理;其过程经过代理来实现的
主要相关变量
final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;
复制代码
dispatchMessage方法在消息被处理时在Looper类中调用
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
复制代码
其处理方法的优先级: 消息对象的回调(callback) > 回调(mCallback成员变量) > handleMessage方法(空方法)
Handler静态建立方法
public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback) {
if (looper == null) throw new NullPointerException("looper must not be null");
if (callback == null) throw new NullPointerException("callback must not be null");
return new Handler(looper, callback, true);
}
public static Handler getMain() {
if (MAIN_THREAD_HANDLER == null) {
MAIN_THREAD_HANDLER = new Handler(Looper.getMainLooper());
}
return MAIN_THREAD_HANDLER;
}
public static Handler mainIfNull(@Nullable Handler handler) {
return handler == null ? getMain() : handler;
}
复制代码
给定looper的handler,主线程Handler;返回给定handler的非空版本
主要是取出队列中消息,并分发给handler处理消息
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper;
private static Observer sObserver;
final MessageQueue mQueue;
final Thread mThread;
复制代码
sThreadLocal静态实例,保存了线程的looper对象
sMainLooper:主线程looper对象
sObserver:监听消息执行状态:开始,结束,异常
mQueue:消息排队队列
mThread:looper对象相关的线程对象
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
复制代码
构造器是私有方法,提供了静态方法,来获取主线成looper对象,当前线程looper对象
启动要调用静态loop()方法,此方法不停的从队列中取出数据,若是数据为空,则跳出循环
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
..........(省略一些代码)
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
......(省略一些代码)
if (observer != null) {
token = observer.messageDispatchStarting();
}
try {
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
if (observer != null) {
observer.dispatchingThrewException(token, msg, exception);
}
throw exception;
} finally {
ThreadLocalWorkSource.restore(origWorkSource);
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
......(省略一些代码)
msg.recycleUnchecked();
}
}
复制代码
流程大体以下:
这里主要分析了线程间通讯的机制;进程间通讯机制依赖Messenger通讯机制;下面对线程间通讯进行一些总结
技术变化都很快,但基础技术、理论知识永远都是那些;做者但愿在余后的生活中,对经常使用技术点进行基础知识分享;若是你以为文章写的不错,请给与关注和点赞;若是文章存在错误,也请多多指教!