网站制作教程ppt,wordpress用户中心界面,怎么把网站封包做app,大学网站建设说明书概述
Handler/Looper机制是android系统非重要且基础的机制#xff0c;即使在rtos或者linux操作系统上开发应用框架时#xff0c;也经常借鉴这个机制。通过该机制机制可以让一个线程循环处理事件#xff0c;事件处理逻辑即在Handler的handleMessge种。本文建议android8.1源码…概述
Handler/Looper机制是android系统非重要且基础的机制即使在rtos或者linux操作系统上开发应用框架时也经常借鉴这个机制。通过该机制机制可以让一个线程循环处理事件事件处理逻辑即在Handler的handleMessge种。本文建议android8.1源码分析这套机制的实现原理。
Handler/Looper Handler顾名思义处理消息message的类Handler也可以发送消息。
Looper顾名思义一个循环体这个循环体本质上就是不断取出Queue种的Message分发给特定的目标具体分发给哪个目标要具体情况具体分析。并且Looper内部含有一个Thread对象很好理解就是Looper这个循环体是在该线程中执行的。
MessageQueue:消息队列通过Handler发送的Message加入到该队列中并且被Looper运行在Thread线程中不断取出又被Handler执行。
执行流程图 应用程序使用Looper
应用程序使用Looper分为两种情况主线程和普通线程
普通线程 * pThis is a typical example of the implementation of a Looper thread,* using the separation of {link #prepare} and {link #loop} to create an* initial Handler to communicate with the Looper.** class LooperThread extends Thread {* public Handler mHandler;** public void run() {* Looper.prepare();** mHandler new Handler() {* public void handleMessage(Message msg) {* // process incoming messages here* }* };** Looper.loop();* }* }
这段代码在Android源码中非常典型使用步骤有三
Looper.prepare创建线程私有的Looper对象。创建处理消息的Handler。Looper.loop开始运作线程一直循环取消息处理消息如果没有消息处理将休眠。
上面代码看似简单越是简单的代码有时候越是难以理解我们要理解上面三个步骤是怎么把ThreadMessageQueueHandler和Looper联系起来的。
Looper.prepare源码 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));}private Looper(boolean quitAllowed) {mQueue new MessageQueue(quitAllowed);mThread Thread.currentThread();}
可以看到prepare就给调用prepare的当前线程创建一个Looper对象Looper对象创建的时候内部新建了MessageQueue和Thread对象特别注意mThread是调用prepare的线程。
Handler对象创建 ** mHandler new Handler() {* public void handleMessage(Message msg) {* // process incoming messages here* }* };
可以想象这里Handler必须要跟前面prepare创建的Looper产生联系才对这个就要看Handler的构造函数
public Handler();
public Handler(Callback callback);
public Handler(Looper looper);
public Handler(Looper looper, Callback callback);
我们要看下上面Handler()构造函数 public Handler() {this(null, false);}public Handler(Callback callback, boolean async) {mLooper Looper.myLooper();if (mLooper null) {throw new RuntimeException(Cant create handler inside thread that has not called Looper.prepare());}mQueue mLooper.mQueue;mCallback callback;mAsynchronous async;}可以看到默认构造函数中非常重要的一句Looper.myLooper会取得当前线程的Looper对象也就是Looper.prepare创建的线程私有的对象同时Handlers MessageQueue来自瑜当前线程Loopers MessageQueue。
注意Thread和Handler是1N关系。比如UI线程就可以有多个Handler对象。
Handler发送和处理消息
按照上面分析调用mHandler可以发送消息然后处理消息在该Handler的handleMessage函数我们看看上述流程是如何实现的。
Looper从MessageQueue中取得一个Message后首先会调用Handler.dispatchMessage进行消息分发后者再根据具体的策略将Message分发给相应的责任人源码如下 Handler.java: /*** Subclasses must implement this to receive messages.*/public void handleMessage(Message msg) {}/*** 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);}}private static void handleCallback(Message message) { message.callback.run();}分发策略
1. Meesage.callback对象不为空优先分发给message.callback。这种情况对应mHandler.post接口发送的runable对象这种情况下Message.callback就是post的runnable对象
public final boolean post(Runnable r);
public final boolean postAtTime(Runnable r, long uptimeMillis);public final boolean post(Runnable r)
{return sendMessageDelayed(getPostMessage(r), 0);
}private static Message getPostMessage(Runnable r) { Message m Message.obtain();m.callback r;return m;
}
2. Handler.mCallback不为空分发给mCallback.handleMessage
3. 前两个都不存在则调用handleMessage比如我们当前普通线程场景override了这个方法就会调用我们自己Handler.handleMessage。这种情况主要对应是Handler send系列接口使用
public boolean sendMessageAtTime(Message msg, long uptimeMillis);
public final boolean sendMessageDelayed(Message msg, long delayMillis);比如如下使用
Message msg mHandler.obtainMessage();
mHandler.sendMessageAtTime(msg,xxxx);public final Message obtainMessage()
{return Message.obtain(this);
}public static Message obtain(Handler h) {Message m obtain();m.target h;return m;
} 可以看到这种情况下Message.target mHandler而Looper在loop中分发代码 */public static void loop() {final Looper me myLooper();if (me null) {throw new RuntimeException(No Looper; Looper.prepare() wasnt called on this thread.);}final MessageQueue queue me.mQueue;// Make sure the identity of this thread is that of the local process,// and keep track of what that identity token actually is.Binder.clearCallingIdentity();final long ident Binder.clearCallingIdentity();for (;;) {Message msg queue.next(); // might block...final long start (slowDispatchThresholdMs 0) ? 0 : SystemClock.uptimeMillis();final long end;try {msg.target.dispatchMessage(msg);end (slowDispatchThresholdMs 0) ? 0 : SystemClock.uptimeMillis();} finally {if (traceTag ! 0) {Trace.traceEnd(traceTag);}}...msg.recycleUnchecked();}} loop循环从Loopers MessageQueue取得消息然后调用Message.target.dispatchMessage正如上面的分析Message.target mHandler所以调用到了Handler.dispatchMessage方法。
总结
1. Handler.post(runnable在Handler.dispatchMessage方法由于优先分发给runnable对象,所以这个runnable对象被执行而不是Handler.handleMessage。
2. 如果使用sendMessage接口那么Handler.dispatchMessage分发给Handler override的handleMessage接口也就是普通线程使用代码中Handlers handleMessage函数。
UI线程 我们知道ActivityThread是主线程的入口点我们看看android UI线程中Looper的使用源码 public static void main(String[] args) { Looper.prepareMainLooper();ActivityThread thread new ActivityThread();thread.attach(false);if (sMainThreadHandler null) {sMainThreadHandler thread.getHandler();}Looper.loop();throw new RuntimeException(Main thread loop unexpectedly exited);}
与普通线程使用Looper类似也分3个步骤
1.准备Looper: Looper.prepareMainLooper
2.创建主线程私有的HandlersMainThreadHandler thread.getHandler
3.开始工作Looper.loop
与普通线程的不同点
1. 普通线程使用Looper.prepare而主线程需要使用Looper.prepareMainLooper
2.Handler不同普通线程生成一个与Looper绑定的Handler即可而主线程是从当前线程总获取
我们分别分析下上面两个不同点
prepareMainLooper public static void prepareMainLooper() { prepare(false);synchronized (Looper.class) {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));}
可以看到prepareMainLooper也使用了prepare不过参数false代表ui线程不能退出并且创建的Looper要赋值给sMainLooper这样其他线程可以通过调用getMainLooper获取该对象。
MainThreadHandler
ActivityThread对象创建时候会在内部同时生成一个Handler对象
final H mH new H()
thread.getHandler获取的就是该mH也就是说ActivityThread中主线程处理消息的Handler之一就是该Handler mH。
loop
分析loop函数之前我们提一下一个图形窗口典型的main函数如下
main() {initialize()//初始化CreateWindow();//创建窗口ShowWindow();while(GetMessage()) {//不断分发处理DispatchMessage();}
}
那么根据前面loop函数的分析其实UI线程的loop函数也是在循环中不断取消息处理消息符合上述模型。
ViewRootImpl
我们知道ViewRootImpl也属于UI线程的范围因为ViewRootImpl创建就是在UI线程中创建那么根据Handler创建的默认构造函数我们知道这个Handler()这个默认的构造函数适合当前线程的Looper绑定的那么ViewRootImpl中Handler()形式构建的Handler也是处理UI线程的相关消息。
final ViewRootHandler mHandler new ViewRootHandler();final class ViewRootHandler extends Handler {public void handleMessage(Message msg) {switch (msg.what) {case MSG_INVALIDATE:((View) msg.obj).invalidate();break;case MSG_INVALIDATE_RECT:final View.AttachInfo.InvalidateInfo info (View.AttachInfo.InvalidateInfo) msg.obj;info.target.invalidate(info.left, info.top, info.right, info.bottom);info.recycle();break;case MSG_PROCESS_INPUT_EVENTS:mProcessInputEventsScheduled false;doProcessInputEvents();break;case MSG_DISPATCH_APP_VISIBILITY:handleAppVisibility(msg.arg1 ! 0);break;case MSG_DISPATCH_GET_NEW_SURFACE:handleGetNewSurface();break;....
Choreographer
Choreographer也是工作在UI主线程的一个重要的类跟Vsync有关我们通过源码看看这个类为什么工作在UI主线程。
看是否是主线程我们要看下Choreographer中的Handler/Looper是基于哪个Thread来创建看下Choreographer的构造函数如下
private Choreographer(Looper looper, int vsyncSource) {mLooper looper;mHandler new FrameHandler(looper); mDisplayEventReceiver USE_VSYNC? new FrameDisplayEventReceiver(looper, vsyncSource): null;mLastFrameTimeNanos Long.MIN_VALUE;mFrameIntervalNanos (long)(1000000000 / getRefreshRate());mCallbackQueues new CallbackQueue[CALLBACK_LAST 1];for (int i 0; i CALLBACK_LAST; i) {mCallbackQueues[i] new CallbackQueue();}}
所以重点就是构建函数中Looper是哪里构建的Choreographer是个单例类所以看下其初始化的代码 // Thread local storage for the choreographer.private static final ThreadLocalChoreographer sThreadInstance new ThreadLocalChoreographer() {Overrideprotected Choreographer initialValue() {Looper looper Looper.myLooper();if (looper null) {throw new IllegalStateException(The current thread must have a looper!);}return new Choreographer(looper, VSYNC_SOURCE_APP);}};
也就是说最终Looper.myLooper获取的是当前线程私有的Looper对象而Choreographer的getInstance是在public ViewRootImpl(Context context, Display display) 构造函数中调用的根据ViewRootImpl小节我们知道ViewRootImpl在主线程构建所以Choreographer是主线程的 Vsync信号处理
我们都知道vsync信号处理的实际逻辑是在ui主线程当中我们看下具体实现首先要看下vsync信号接受和处理的地方这个在Choreographer当中 private final class FrameDisplayEventReceiver extends DisplayEventReceiverimplements Runnable {private boolean mHavePendingVsync;private long mTimestampNanos;private int mFrame;public FrameDisplayEventReceiver(Looper looper, int vsyncSource) {super(looper, vsyncSource);}Overridepublic void onVsync(long timestampNanos, int builtInDisplayId, int frame) {...mTimestampNanos timestampNanos;mFrame frame;Message msg Message.obtain(mHandler, this);msg.setAsynchronous(true);mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);}Overridepublic void run() {mHavePendingVsync false;doFrame(mTimestampNanos, mFrame);}
可以看到接收到vsync信号之后使用mHandler向该Handler所在的线程发送消息根据Choreographer小节我们知道这里mHandler和其Looper是UI线程的所以上面代码中发送的消息在主线程中处理而FrameDisplayEventReceiver是个runnable对象所以最终主线程收到这消息的处理函数是doFrame函数: Trace.traceBegin(Trace.TRACE_TAG_VIEW, Choreographer#doFrame);AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);mFrameInfo.markInputHandlingStart();doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);mFrameInfo.markAnimationsStart();doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);mFrameInfo.markPerformTraversalsStart();doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
vsync信号过来在主线程处理 最终处理函数是doFrame-doCallbacks而doCallbacks就是要处理应用已经请求且记录到queue里面的各种事件比如应用请求渲染的时候调用invalidate调用栈
invalidate() : ViewRootImpl.java---scheduleTraversals() : ViewRootImpl.java---mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
最终postCallback的实现 private void postCallbackDelayedInternal(int callbackType,Object action, Object token, long delayMillis) {synchronized (mLock) {final long now SystemClock.uptimeMillis();final long dueTime now delayMillis;//将要执行的回调封装成CallbackRecord对象保存到mCallbackQueues数组中mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);//函数执行时间到if (dueTime now) {scheduleFrameLocked(now);} else {//通过异步消息方式实现函数延时执行Message msg mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);msg.arg1 callbackType;msg.setAsynchronous(true);mHandler.sendMessageAtTime(msg, dueTime);}}1.将请求的事件保存在mCallbackQueue等到vsync信号来到doFrame中取出执行。
2. 发送MSG_DO_SCHEDULE_CALLBACK消息最终调用native层的mDisplayEventReceiver.scheduleVsync();请求接收下一次vsync信号