handler源码解析

handler源码分析

1.基本使用

handler:发送和接受消息

looper:用于轮询消息队列

MessageQueue:消息队列用于存储消息和管理消息

kotlin 复制代码
//UI线程
val handler = object : Handler(Looper.getMainLooper()) {
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            when (msg.obj) {
                CODE_UPDATE -> {
                    //处理消息
                }
            }
        }
    }

	
    Thread {
        val message = Message.obtain()
        message.what = CODE_UPDATE


        //发送消息
        handler.sendMessage(message)


        //发送一条延时消息 
        handler.sendMessageDelayed(message,200)
    }.start()


	Thread{
		handler.post {
        	// 在UI线程执行的任务
    	}
	}

1.创建handler对象

2.使用post方法或者sendMessage方法

3.在handler所在的线程,进行消息处理

两种发送信息的方式,一种是发送Message,一种是post。

分别看下两种方式的源码处理

2.流程解析

2.1 handler创建

less 复制代码
//android.os.Handler
		
public Handler(@NonNull Looper looper) {
    this(looper, null, false);
}

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

class Handler{
    final Looper mLooper;
    final MessageQueue mQueue;
    ...
}

可以看到,在handler创建的时候,需要传入一个looper,而mQueue被Looper所持有

2.2 looper创建

在ActivityThread中的main方法中,已经为我们创建了looper

arduino 复制代码
android.app.ActivityThread
	
public static void main(String[] args) {

    ... 省略代码

    //初始化looper和MessageQueue
    Looper.prepareMainLooper();
    
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
     }

    ... 省略代码

    //轮询
    Looper.loop();

    throw new RuntimeException("Main thread loop unexpectedly exited");
}

Looper.prepareMainLooper()进行了Looper和MessageQueue的创建

csharp 复制代码
android.os.Looper

public static void prepareMainLooper() {

    //不可退出
    prepare(false);

    synchronized (Looper.class) {
        //如果looper已经存在,则抛出异常
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}
		
private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

从代码可以看出,主要是通过Looper.prepare方法进行创建looper,先调用sThreadLocal.get()获取Looper,如果Looper已经存在,则抛出异常。如果不存在,则创建Looper并且设置到ThreadLocal中。再来看看ThreadLocal的具体实现

swift 复制代码
android.os.Looper

public final class Looper {
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
}
ini 复制代码
java.lang.ThreadLocal

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
 }

ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}
		
public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null){
        map.set(this, value);
    }else{
        createMap(t, value);
    }
}

ThreadLocal的作用是为每个线程提供一个独立的变量副本,通过ThreadLocalMap来实现对每个线程的变量副本的存储和获取。获取到当前线程对应的ThreadLocalMap,static final修饰的threadLocal变量作为key,value则是looper实例,进行存储。由于key永远是同一个,再加Looper.prepare会先判断当前线程是否存在looper,所以Looper在每个线程中只会存在一个Looper

2.3 MessageQueue创建

ini 复制代码
android.os.Looper

private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

在looper的构造函数中,创建了MessageQueue,这个时候handler和looper,messagequeue就绑定在一起了。

2.4 handler.sendMessage

less 复制代码
android.os.Handler

public final boolean sendMessage(@NonNull Message msg) {
    return sendMessageDelayed(msg, 0);
}

public final boolean post(@NonNull Runnable r) {
    return sendMessageDelayed(getPostMessage(r), 0);
}
		
    //post 将runnable设置为msg的callback
private static Message getPostMessage(Runnable r) {
        	Message m = Message.obtain();
        	m.callback = r;
        	return m;
    	}

public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
    if (delayMillis < 0) {
        delayMillis = 0;
    }
			
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}

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);
}

private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
            long uptimeMillis) {
    msg.target = this;
    msg.workSourceUid = ThreadLocalWorkSource.getUid();

    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}

通过上面的代码可以看出,无论是sendMessage还是post都会走到sendMessageDelayed,在走到sendMessageAtTime方法,uptimeMillis则是一个具体的时间点,最后走到了enqueueMessage方法,msg.target = this,指向了当前handler。最后由queue.enqueueMessage进行处理。在一开始创建handler的时候,已经看到了mQueue是MessageQueue。接下来看MessageQueue是怎么处理这个消息的

ini 复制代码
android.os.MessageQueue

boolean enqueueMessage(Message msg, long when) {
    if (msg.target == null) {
        throw new IllegalArgumentException("Message must have a target.");
    }
		
    //加锁
    synchronized (this) {
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }
			
        //Looper.myLooper().quit(); 应用退出的时候才会被标记为true
        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 {
            Message prev;
            for (;;) {
                prev = p;
                p = p.next;
                if (p == null || when < p.when) {
                    break;
                }
                if (needWake && p.isAsynchronous()) {
                    needWake = false;
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }
        }
        
        //唤醒
        if (needWake) {
            nativeWake(mPtr);
        }
            
        return true;
    }

插入队列这里进行了加锁,保证了线程安全。从代码看出这个队列是优先级队列,按照msg的when进行排序。当头节点为null或者头节点的when大于msg的when时,msg作为头节点。如果msg的when大于头节点,轮询将msg插入到合适的位置。

2.5 Looper.loop

已经将msg插入到messagequeue中,接下来看看loop是怎么处理的。

java 复制代码
android.os.Looper

public static void loop() {
    //获取looper
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }

    for (;;) {
        if (!loopOnce(me, ident, thresholdOverride)) {
            return;
            }
        }
    }
}


private static boolean loopOnce(final Looper me,final long ident, final int thresholdOverride) {
    //取出队列中的消息
    Message msg = me.mQueue.next(); // might block
    if (msg == null) {
        return false;
    }
		
    ...省略代码
    
    //msg.target就是handler
     msg.target.dispatchMessage(msg);

    ...省略代码

    msg.recycleUnchecked();

    return true;
}
ini 复制代码
android.os.MessageQueue


Message next() {
    final long ptr = mPtr;
    if (ptr == 0) {
        return null;
    }

    int pendingIdleHandlerCount = -1; // -1 only during first iteration
    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) {
                // Stalled by a barrier.  Find the next asynchronous message in the queue.
                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; // release the reference to the handler

            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;
    }
}

在循环中,程序不断地从消息队列中获取消息。如果成功获取到消息,程序会判断当前时间是否小于消息的触发时间(msg.when)。如果是,会计算出下一次轮询超时的时间(nextPollTimeoutMillis),然后通过调用nativePollOnce方法来进行等待,该方法底层会调用Linux的epoll方法。

如果当前消息队列中没有任何消息,程序将会无限等待,直到有新的消息到达。这个过程会不断重复,保证程序能够及时处理消息

msg.target是handler,在取出msg后,最终会调用到handler的dispatchMessage方法。接下来又会执行msg.recycleUnchecked()方法。

ini 复制代码
void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        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++;
            }
        }
    }

这里将msg的标记进行置空,释放所有资源,在判断当前队列的msg数量是否小于MAX_POOL_SIZE(50),如果小于则插入到表头。

2.6 Handler.dispatchMessage

typescript 复制代码
public void dispatchMessage(@NonNull Message msg) {
    //post runnable设置msg的callback
    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();
}

如果是post过来的消息,一开始传入的时候已经将runnable设为msg的callback,这个时候直接执行run函数,否则由handler的callback回调处理。

相关推荐
千里马学框架13 小时前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台13 小时前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone14 小时前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc14 小时前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo16 小时前
Kotlin 协程中的 Job 结构化并发与取消
android
sun00770016 小时前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼17 小时前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone18 小时前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen18 小时前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone18 小时前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui