深入理解View知识系列一- setContentView和LayoutInflater源码原理分析
深入理解View知识系列二- View底层工作原理以及View的绘制流程
深入理解View知识系列三-Window机制、Canvas的由来、Android事件的由来
深入理解View知识系列四-View的测量规则以及三大方法流程
在setContentView之后,Activity会继续走它自己的生命周期方法,接着会走到ActivityThread中的handleResumeActivity中,在这个方法中会执行如下几部(只涉及View知识,其他的逻辑会在以后说)。
通过这几步我们还总结了两点
1.Activity是先回调了Activity的onResume之后才开始添加DecorView的,也就是说在oResume中是不能得到View的宽高参数的
2.Activity也是通过WindowManager来添加View的,这和我们平时自己使用WindowManger来添加一个View的流程类似。
WindowManger的是实现类是WindowManagerImpl,在WindowManagerImpl中包括addView在内操作View的三大方法全部使用了桥接到了WindowManagerGloble中,WindowManagerGloble是一个单例类,那么也就说明每个进程中所有对View的三大操作全部都只在这一个类中进行管理,在这里主要执行了如下几步。
在WindowManagerGloble中创建了ViewRootImpl,并调用了它的setView方法,逻辑转入到ViewRootImpl中,主要逻辑如下
顾名思义就是一个窗口,Android中所有的视图都需要通过Window来展示,它是一个抽象类,例如Activity、Toast、Dialog、PopupWindow等都必须通过Window才可以展示,它内部直接操作管理着View,可以说它是View的直接管理者,也可以说是相辅相成,互相依赖,谁离了谁都不行,而Window又分为三大类,这一点体现在WindowManager.LayoutParams中声明的常量中,这些常量用于type这个参数上,而且从声明中可以看出它们是分层级的,层级大的会覆盖在层级小的上面,如下
public static final int FIRST_APPLICATION_WINDOW = 1;
public static final int TYPE_BASE_APPLICATION = 1;
public static final int TYPE_APPLICATION = 2;
public static final int TYPE_APPLICATION_STARTING = 3;
public static final int TYPE_DRAWN_APPLICATION = 4;
public static final int LAST_APPLICATION_WINDOW = 99;
public static final int FIRST_SUB_WINDOW = 1000;
public static final int TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW;
public static final int TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1;
public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2;
public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3;
public static final int TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4;
public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;
public static final int LAST_SUB_WINDOW = 1999;
public static final int FIRST_SYSTEM_WINDOW = 2000;
public static final int TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW;
public static final int TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1;
public static final int TYPE_PHONE = FIRST_SYSTEM_WINDOW+2;
public static final int TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3;
public static final int TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4;
public static final int TYPE_TOAST = FIRST_SYSTEM_WINDOW+5;
....
public static final int LAST_SYSTEM_WINDOW = 2999;
如果没有设置type这个字段的值的话,默认是应用及Window,是TYPE_APPLICATION,这里从源码的WindowManager.LayoutParams的构造方法中可以看出来,
//LayoutParams的构造方法
public LayoutParams() {
super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
//默认值是2
type = TYPE_APPLICATION;
format = PixelFormat.OPAQUE;
}
PhoneWindow是Window的唯一实现类,内部管理着最顶层的View,即DecorView
一个接口,内部定义了操作View的三个方法,即addView、updateViewLayout、removeView
也是一个接口继承了ViewManager,也是WindowManagerService代理包装类,这一点从context.getSystemService的源码中有体现,来看一下
//1.ContextImpl
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
//2.SystemServiceRegistry
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
//3.registerService
private static void registerService(String serviceName, Class serviceClass,
ServiceFetcher serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
//4.注册服务
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher() {
@Override
public WindowManager createService(ContextImpl ctx) {
return new WindowManagerImpl(ctx);
}});
WindowManager的实现类,从上面注册服务的源码可以看出来,最终返回的是WindowManagerImpl,但是它并没有真正实现View的三大操作,全部桥接到了WindowMangerGloble
真正实现View三大操作的类,它是一个单例类,它还管理着所有Window中的ViewRootImpl、DecorView、LayoutParams
整个View树的根,在WindowManagerGloble中的addView中被创建,是顶层DecorView的ViewParent,控制着整个View树的运作,包括measure、layout、draw、重绘、事件传递派发等
一个aidl接口,它的真的实现类是Session,它是一个Binder对象,用来和WindowManagerService建立连接,在ViewRootImpl的setView中最终也是通过它和WindowManagerService通信完成了Window的添加的。这个Session是应用唯一的,它的创建时在WindowManagerGloable中通过getWindowSession获取的
IWindowSession的真正实现类,这一点在WindowManagerGloble的获取中可以体现
//WindowManagerGloble
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
IWindowManager windowManager = getWindowManagerService();
//调用WMS的openSession
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
//WindowManagerService
@Override
public IWindowSession openSession(IWindowSessionCallback callback, IInputMethodClient client,
IInputContext inputContext) {
if (client == null) throw new IllegalArgumentException("null client");
if (inputContext == null) throw new IllegalArgumentException("null inputContext");
//真正返回的是Session
Session session = new Session(this, callback, client, inputContext);
return session;
}
也是一个aidl接口,它的实现是在ViewRootImpl中的内部类W,在添加window的时候会将ViewRootImpl中的W传递到WMS中并封装成WindowState对象,这个类会监听一些窗口的变化并回调给ViewRootImpl中的W类,也可以简单的理解成就是一个WMS的远程回调接口
static class W extends IWindow.Stub {
private final WeakReference mViewAncestor;
private final IWindowSession mWindowSession;
W(ViewRootImpl viewAncestor) {
mViewAncestor = new WeakReference(viewAncestor);
mWindowSession = viewAncestor.mWindowSession;
}
@Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
Configuration newConfig, Rect backDropFrame, boolean forceLayout,
boolean alwaysConsumeNavBar) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchResized(frame, overscanInsets, contentInsets,
visibleInsets, stableInsets, outsets, reportDraw, newConfig, backDropFrame,
forceLayout, alwaysConsumeNavBar);
}
}
@Override
public void moved(int newX, int newY) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchMoved(newX, newY);
}
}
@Override
public void dispatchAppVisibility(boolean visible) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchAppVisibility(visible);
}
}
@Override
public void dispatchGetNewSurface() {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchGetNewSurface();
}
}
.....
}
其实可以把它理解成是真正的画布,我们应用绘制View用的Canvas就是通过Surface来创建的,每一个Window中都存在一个自己的Surface,这个声明在ViewRootImpl中,但是ViewRootImpl中声明的Surface只是一个空壳,在绘制之前会调用relayoutWindow到WMS中去真正的创建Surface,它需要通过系统的SurfaceFlinger来整合显示,简单说就是Window需要通过Surface创建的Canvas来绘制要显示的内容,然后系统底层来控制Surface的整合展示,我们看来看一下Surface真正的创建过程和Canvas是怎么得来的
//1.ViewRootImpl中声明的Surface
final Surface mSurface = new Surface();
//2.在ViewRootImpl的绘制方法中,也就是performTraversals中会在执行performDraw之前先去WMS端获取到native层Sureface
private void performTraversals() {
//顶层的View,可以理解成是DecorView
final View host = mView;
...
//通知被添加到窗口了,传入了mAttachInfo
host.dispatchAttachedToWindow(mAttachInfo, 0);
//调用relayoutWindow方法去获取native层的Surface
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
...
//measure过程
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
....
//layout过程
performLayout(lp, desiredWindowWidth, desiredWindowHeight);
....
//通知layout完成了
mAttachInfo.mTreeObserver.dispatchOnGlobalLayout();
....
//draw过程
performDraw();
}
//3.ViewRootImpl的relayoutWindow方法,去获取native行Surface
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
....
//调用了mWindowSession的relayout方法,上面我们知道IWindowSession真正实现是Session
int relayoutResult = mWindowSession.relayout(
mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f),
viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingConfiguration,
mSurface);//最后一个参数传入了ViewRootImpl中的空壳Sureface
....
return relayoutResult;
}
//4.Session中的relayoutWindow
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
int requestedWidth, int requestedHeight, int viewFlags,
int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outsets, Rect outBackdropFrame,
Configuration outConfig, Surface outSurface) {
//直接调用了WMS的relayoutWIndow
int res = mService.relayoutWindow(this, window, seq, attrs,
requestedWidth, requestedHeight, viewFlags, flags,
outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
outStableInsets, outsets, outBackdropFrame, outConfig, outSurface);
return res;
}
//5.WindowManagerService中的relayoutWindow方法
public int relayoutWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int requestedWidth,
int requestedHeight, int viewVisibility, int flags,
Rect outFrame, Rect outOverscanInsets, Rect outContentInsets,
Rect outVisibleInsets, Rect outStableInsets, Rect outOutsets, Rect outBackdropFrame,
Configuration outConfig, Surface outSurface) {
....
//创建SurfaceControl并获取native中创建Surface
result = createSurfaceControl(outSurface, result, win, winAnimator);
....
}
//6.WindowManagerService中的createSurfaceControl方法
private int createSurfaceControl(Surface outSurface, int result, WindowState win,
WindowStateAnimator winAnimator) {
if (!win.mHasSurface) {
result |= RELAYOUT_RES_SURFACE_CHANGED;
}
WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked();
if (surfaceController != null) {
//获取native层的Surface
surfaceController.getSurface(outSurface);
} else {
outSurface.release();
}
return result;
}
//7.WindowSurfaceController中的getSurface方法
void getSurface(Surface outSurface) {
//调用了Surface中的copyFrom方法,从方法名体现的是将native层的Surface复制到客户端的空壳中
outSurface.copyFrom(mSurfaceControl);
}
//8.在调用draw之前会先创建Canvas对象
*/
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
boolean scalingRequired, Rect dirty) {
final Canvas canvas;
try {
//使用Surface创建一个Canvas,方法中也是调用了native方法
anvas = mSurface.lockCanvas(dirty);
if (left != dirty.left || top != dirty.top || right != dirty.right
|| bottom != dirty.bottom) {
attachInfo.mIgnoreDirtyState = true;
}
canvas.setDensity(mDensity);
}catch (Surface.OutOfResourcesException e) {
handleOutOfResourcesException(e);
return false;
} catch (IllegalArgumentException e) {
mLayoutRequested = true; // ask wm for a new surface next time.
return false;
}
....
try {
canvas.translate(-xoff, -yoff);
if (mTranslator != null) {
mTranslator.translateCanvas(canvas);
}
canvas.setScreenDensity(scalingRequired ? mNoncompatDensity : 0);
attachInfo.mSetIgnoreDirtyState = false;
//调用View的draw方法,并传入刚刚创建的Canvas对象
mView.draw(canvas);
drawAccessibilityFocusedDrawableIfNeeded(canvas);
} finally {
if (!attachInfo.mSetIgnoreDirtyState) {
// Only clear the flag if it was not set during the mView.draw() call
attachInfo.mIgnoreDirtyState = false;
}
}
....
}
源码位置:/frameworks/base/core/java/android/view/ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
...
//最终在这里调用了绘制
requestLayout();
...
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
//创建了一个InputChannel实例,可以理解为是和Server端事件消息通道
mInputChannel = new InputChannel();
}
//通过WMS添加Window,mWindow是IWindow类型,ViewRootImpl的内部类W,最后一个参数传入了刚刚创建的通道对象
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
//根据WMS返回的值判断Window是否添加成功,不成功则抛出相应的异常
if (res < WindowManagerGlobal.ADD_OKAY) {
mAttachInfo.mRootView = null;
mAdded = false;
mFallbackEventHandler.setView(null);
unscheduleTraversals();
setAccessibilityFocus(null, null);
switch (res) {
case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
throw new WindowManager.BadTokenException(
"Unable to add window -- token " + attrs.token
+ " is not valid; is your activity running?");
case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
throw new WindowManager.BadTokenException(
"Unable to add window -- token " + attrs.token
+ " is not for an application");
case WindowManagerGlobal.ADD_APP_EXITING:
throw new WindowManager.BadTokenException(
"Unable to add window -- app for token " + attrs.token
+ " is exiting");
case WindowManagerGlobal.ADD_DUPLICATE_ADD:
throw new WindowManager.BadTokenException(
"Unable to add window -- window " + mWindow
+ " has already been added");
case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
// Silently ignore -- we would have just removed it
// right away, anyway.
return;
case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
throw new WindowManager.BadTokenException("Unable to add window "
+ mWindow + " -- another window of type "
+ mWindowAttributes.type + " already exists");
case WindowManagerGlobal.ADD_PERMISSION_DENIED:
throw new WindowManager.BadTokenException("Unable to add window "
+ mWindow + " -- permission denied for window type "
+ mWindowAttributes.type);
case WindowManagerGlobal.ADD_INVALID_DISPLAY:
throw new WindowManager.InvalidDisplayException("Unable to add window "
+ mWindow + " -- the specified display can not be found");
case WindowManagerGlobal.ADD_INVALID_TYPE:
throw new WindowManager.InvalidDisplayException("Unable to add window "
+ mWindow + " -- the specified window type "
+ mWindowAttributes.type + " is not valid");
}
throw new RuntimeException(
"Unable to add window -- unknown error code " + res);
}
...
if (mInputChannel != null) {
if (mInputQueueCallback != null) {
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
//创建一个用来接收事件的类
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
//设置DecorView的Parent为ViewRootImpl
view.assignParent(this);
...
//创建了一堆的InputStage来处理相应的输入事件,在下面会分析触摸事件时用到
CharSequence counterSuffix = attrs.getTitle();
mSyntheticInputStage = new SyntheticInputStage();
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
"aq:native-post-ime:" + counterSuffix);
InputStage earlyPostImeStage = new EarlyPostImeInputStage(nativePostImeStage);
InputStage imeStage = new ImeInputStage(earlyPostImeStage,
"aq:ime:" + counterSuffix);
InputStage viewPreImeStage = new ViewPreImeInputStage(imeStage);
InputStage nativePreImeStage = new NativePreImeInputStage(viewPreImeStage,
"aq:native-pre-ime:" + counterSuffix);
mFirstInputStage = nativePreImeStage;
mFirstPostImeInputStage = earlyPostImeStage;
}
源码位置:/frameworks/base/services/core/java/com/android/server/wm/Session.java
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
Rect outOutsets, InputChannel outInputChannel) {
//什么都没做,直接调用了WMS的addWindow方法
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}
源码位置:源码位置:/frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
int[] appOp = new int[1];
//如果是系统窗口检查是否有权限
int res = mPolicy.checkAddPermission(attrs, appOp);
if (res != WindowManagerGlobal.ADD_OKAY) {
return res;
}
...
final int type = attrs.type;
synchronized(mWindowMap) {
...
//如果mWindowMap中包含这个Window,说明之前添加过,返回添加失败
if (mWindowMap.containsKey(client.asBinder())) {
Slog.w(TAG_WM, "Window " + client + " is already added");
return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}
//如果要添加的是一个子Window
if (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) {
//获取子Window依赖的父Window
attachedWindow = windowForClientLocked(null, attrs.token, false);
//如果父Window不存在,也返回添加失败,这些失败的处理在ViewRootImpl中
if (attachedWindow == null) {
Slog.w(TAG_WM, "Attempted to add window with token that is not a window: "
+ attrs.token + ". Aborting.");
return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
}
//如果父Window的type也是一个子Window,返回添加失败,子Window不能依赖子Window
if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
&& attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
Slog.w(TAG_WM, "Attempted to add window with token that is a sub-window: "
+ attrs.token + ". Aborting.");
return WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN;
}
}
...
//创建WindowState,传入了App端传过来的client,就是IWindow,当窗口发生变化会回调客户端的ViewRootImpl中的W类
WindowState win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
...
//如果传入的客户端通道不为空,则注册消息通道
final boolean openInputChannels = (outInputChannel != null
&& (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
if (openInputChannels) {
win.openInputChannel(outInputChannel);
}
//android7.1对于类型是TYPE_TOAST的窗口做了限制,防止一个应用的悬浮窗一直悬浮在另一个应用上造成干扰,如果重复添加类型是TOAST的窗口则会抛出异常,如果没有则会正常展示,但是3.5秒后会自动消失,但是3.5未完成窗口的取消则会抛出ANR异常
if (type == TYPE_TOAST) {
if (!getDefaultDisplayContentLocked().canAddToastWindowForUid(callingUid)) {
Slog.w(TAG_WM, "Adding more than one toast window for UID at a time.");
return WindowManagerGlobal.ADD_DUPLICATE_ADD;
}
if (addToastWindowRequiresToken
|| (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0
|| mCurrentFocus == null
|| mCurrentFocus.mOwnerUid != callingUid) {
//发送ANR异常消息
mH.sendMessageDelayed(
mH.obtainMessage(H.WINDOW_HIDE_TIMEOUT, win),
win.mAttrs.hideTimeoutMilliseconds);
}
}
// From now on, no exceptions or errors allowed!
res = WindowManagerGlobal.ADD_OKAY;
....
return res;
}
源码位置:源码位置:/frameworks/base/services/core/java/com/android/server/wm/WindowState.java
void openInputChannel(InputChannel outInputChannel) {
if (mInputChannel != null) {
throw new IllegalStateException("Window already has an input channel.");
}
String name = makeInputChannelName();
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
mInputChannel = inputChannels[0];
mClientChannel = inputChannels[1];
mInputWindowHandle.inputChannel = inputChannels[0];
if (outInputChannel != null) {
mClientChannel.transferTo(outInputChannel);
mClientChannel.dispose();
mClientChannel = null;
} else {
mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
}
//将消息通道注册到native层,当有事件产生的时候会出发ViewRootImpl中的WindowInputEventReceiver
mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
}
源码位置:/frameworks/base/core/java/android/view/ViewRootImpl.java
final class WindowInputEventReceiver extends InputEventReceiver {
public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
//接受到事件会到这里进行分发处理
@Override
public void onInputEvent(InputEvent event) {
//然后调用了enqueueInputEvent进行处理
enqueueInputEvent(event, this, 0, true);
}
@Override
public void onBatchedInputEventPending() {
if (mUnbufferedInputDispatch) {
super.onBatchedInputEventPending();
} else {
scheduleConsumeBatchedInput();
}
}
@Override
public void dispose() {
unscheduleConsumeBatchedInput();
super.dispose();
}
}
//构造函数
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null");
}
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
//nativeInit是一个native方法
mReceiverPtr = nativeInit(new WeakReference(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
//当native层发来事件时会走到这里,也就是会调用到ViewRootImpl中WindowInputEventReceiver的这个方法
@SuppressWarnings("unused")
private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
//调用实现类的onInputEvnet方法
onInputEvent(event);
}
源码位置:/frameworks/base/core/java/android/view/ViewRootImpl.java
void enqueueInputEvent(InputEvent event,
InputEventReceiver receiver, int flags, boolean processImmediately) {
adjustInputEventForCompatibility(event);
QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags);
//将事件消息进行排队处理
QueuedInputEvent last = mPendingInputEventTail;
if (last == null) {
mPendingInputEventHead = q;
mPendingInputEventTail = q;
} else {
last.mNext = q;
mPendingInputEventTail = q;
}
mPendingInputEventCount += 1;
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
mPendingInputEventCount);
if (processImmediately) {
//如果是立即处理
doProcessInputEvents();
} else {
//否则使用Handler进行调度,最后也会执行doProcessInputEvents
scheduleProcessInputEvents();
}
}
//doProcessInputEvents方法
void doProcessInputEvents() {
//遍历队列里的所有事件
while (mPendingInputEventHead != null) {
QueuedInputEvent q = mPendingInputEventHead;
mPendingInputEventHead = q.mNext;
if (mPendingInputEventHead == null) {
mPendingInputEventTail = null;
}
q.mNext = null;
mPendingInputEventCount -= 1;
Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName,
mPendingInputEventCount);
long eventTime = q.mEvent.getEventTimeNano();
long oldestEventTime = eventTime;
if (q.mEvent instanceof MotionEvent) {
MotionEvent me = (MotionEvent)q.mEvent;
if (me.getHistorySize() > 0) {
oldestEventTime = me.getHistoricalEventTimeNano(0);
}
}
mChoreographer.mFrameInfo.updateInputEventTime(eventTime, oldestEventTime);
//处理每一个事件
deliverInputEvent(q);
}
//当上面所有事件处理完成则移除标记
if (mProcessInputEventsScheduled) {
mProcessInputEventsScheduled = false;
mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
}
}
//deliverInputEvent方法
private void deliverInputEvent(QueuedInputEvent q) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
q.mEvent.getSequenceNumber());
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onInputEvent(q.mEvent, 0);
}
//根据事件的不同获取到不同的InputStage
InputStage stage;
if (q.shouldSendToSynthesizer()) {
stage = mSyntheticInputStage;
} else {
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
//接着使用对应的InputStage处理事件,在上面最开始的时候我们看的ViewRootImpl的setView
//方法中创建了很多不同InputStage,这里我们分析一个View的事件处理,即ViewPostImeInputStage
// InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
if (stage != null) {
//调用deliver
stage.deliver(q);
} else {
finishInputEvent(q);
}
}
//InputStage
public final void deliver(QueuedInputEvent q) {
if ((q.mFlags & QueuedInputEvent.FLAG_FINISHED) != 0) {
forward(q);
} else if (shouldDropInputEvent(q)) {
finish(q, false);
} else {
//这里又会调用子类重写的onProcess
apply(q, onProcess(q));
}
}
//ViewPostImeInputStage
@Override
protected int onProcess(QueuedInputEvent q) {
if (q.mEvent instanceof KeyEvent) {
//按键事件
return processKeyEvent(q);
} else {
final int source = q.mEvent.getSource();
if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
//触摸屏事件
return processPointerEvent(q);
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
return processTrackballEvent(q);
} else {
return processGenericMotionEvent(q);
}
}
}
//ViewRootImpl中的内部类ViewPostImeInputStage中的processKeyEvent方法
private int processKeyEvent(QueuedInputEvent q) {
final KeyEvent event = (KeyEvent)q.mEvent;
// 当前的mView是DecorView,调用了它的dispatchKeyEvent
if (mView.dispatchKeyEvent(event)) {
return FINISH_HANDLED;
}
...
return FORWARD;
}
//DecorView中的dispatchKeyEvent方法
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
//获取事件类型
final int keyCode = event.getKeyCode();
final int action = event.getAction();
final boolean isDown = action == KeyEvent.ACTION_DOWN;
...
//如果Window还存在
if (!mWindow.isDestroyed()) {
//获取Window的Callback,这里我们以前分析过
final Window.Callback cb = mWindow.getCallback();
final boolean handled = cb != null && mFeatureId < 0 ?
//调用callback的dispatchKeyEvent
cb.dispatchKeyEvent(event)
: super.dispatchKeyEvent(event);
if (handled) {
return true;
}
}
return isDown ? mWindow.onKeyDown(mFeatureId, event.getKeyCode(), event)
: mWindow.onKeyUp(mFeatureId, event.getKeyCode(), event);
}
//Activity中的dispatchKeyEvent方法
public boolean dispatchKeyEvent(KeyEvent event) {
//这是一个空方法
onUserInteraction();
...
View decor = mDecor;
if (decor == null) decor = win.getDecorView();
//最终调用了KeyEvent自己的dispatch方法,注意传入的this
return event.dispatch(this, decor != null
? decor.getKeyDispatcherState() : null, this);
}
//KeyEvent中dispatch方法,上面传递的第一参数this,也就是Activity自己
public final boolean dispatch(Callback receiver, DispatcherState state,
Object target) {
switch (mAction) {
case ACTION_DOWN: {
mFlags &= ~FLAG_START_TRACKING;
//onKeyDown,还是会回调会Activity中的onKeyDown
boolean res = receiver.onKeyDown(mKeyCode, this);
...
return res;
}
case ACTION_UP:
...
//还是会回调会Activity中的onKeyUp
return receiver.onKeyUp(mKeyCode, this);
case ACTION_MULTIPLE:
final int count = mRepeatCount;
final int code = mKeyCode;
if (receiver.onKeyMultiple(code, count, this)) {
return true;
}
if (code != KeyEvent.KEYCODE_UNKNOWN) {
mAction = ACTION_DOWN;
mRepeatCount = 0;
boolean handled = receiver.onKeyDown(code, this);
if (handled) {
mAction = ACTION_UP;
receiver.onKeyUp(code, this);
}
mAction = ACTION_MULTIPLE;
mRepeatCount = count;
return handled;
}
return false;
}
return false;
}
//ViewRootImple中的内部类ViewPostImeInputStage中的processPointerEvent方法
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
mAttachInfo.mUnbufferedDispatchRequested = false;
//获取当前事件的View,最开始肯定是DecorView
final View eventTarget =
(event.isFromSource(InputDevice.SOURCE_MOUSE) && mCapturingView != null) ?
mCapturingView : mView;
mAttachInfo.mHandlingPointerEvent = true;
//因为DecorView并没有重写dispatchPointerEvent方法,所以最终调用View的dispatchPointerEvent,
boolean handled = eventTarget.dispatchPointerEvent(event);
...
return handled ? FINISH_HANDLED : FORWARD;
}
public final boolean dispatchPointerEvent(MotionEvent event) {
if (event.isTouchEvent()) {
//熟悉了吧
return dispatchTouchEvent(event);
} else {
return dispatchGenericMotionEvent(event);
}
}