1 起源
Android中Activity的setContentView会调用getWindow().setContentView()办法,getWindow返回的是一个Window对象,在Android中的惟一实现是PhoneWindow:
private void installDecor() { mForceDecorInstall = false; if (mDecor == null) { //创立DecorView ** mDecor = generateDecor(-1)**; ... } else { mDecor.setWindow(this); } if (mContentParent == null) { //ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); ** mContentParent = generateLayout(mDecor);** } ... }
在PhoneWindow中会装置DecorView,找到DecorView中的ContentParent,而后把咱们传进来布局增加到ContentParent中.(setContentView的父布局)
在ActivityThread的handleResumeActivity()办法中
//mVisibleFromClient activity中属性 默认为true if (a.mVisibleFromClient) { if (!a.mWindowAdded) { a.mWindowAdded = true; wm.addView(decor, l); } else { a.onWindowAttributesChanged(l); } }
windowManager在Android中的实现是WindowManagerImpl.
@Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); // private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance(); 单例 mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow, mContext.getUserId()); }
WindowManagerGlobal的addView,在这里创立了ViewRootImpl
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow, int userId) { ... ViewRootImpl root; View panelParentView = null; root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); mViews.add(view); mRoots.add(root); mParams.add(wparams); // do this last because it fires off messages to start doing things try { root.setView(view, wparams, panelParentView, userId); } catch (RuntimeException e) { ... throw e; } } }
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) { ... mView = view; requestLayout(); //接管事件 mInputEventReceiver = new WindowInputEventReceiver(inputChannel, Looper.myLooper()); }
final class WindowInputEventReceiver extends InputEventReceiver { public WindowInputEventReceiver(InputChannel inputChannel, Looper looper) { super(inputChannel, looper); } @Override public void onInputEvent(InputEvent event) { //事件散发的终点 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "processInputEventForCompatibility"); List<InputEvent> processedEvents; try { processedEvents = mInputCompatProcessor.processInputEventForCompatibility(event); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } if (processedEvents != null) { if (processedEvents.isEmpty()) { // InputEvent consumed by mInputCompatProcessor finishInputEvent(event, true); } else { for (int i = 0; i < processedEvents.size(); i++) { enqueueInputEvent( processedEvents.get(i), this, QueuedInputEvent.FLAG_MODIFIED_FOR_COMPATIBILITY, true); } } } else { enqueueInputEvent(event, this, 0, true); } } } void enqueueInputEvent(InputEvent event, InputEventReceiver receiver, int flags, boolean processImmediately) { QueuedInputEvent q = obtainQueuedInputEvent(event, receiver, flags); if (processImmediately) { doProcessInputEvents(); } else { //也会调用到doProcessInputEvents() scheduleProcessInputEvents(); } } void doProcessInputEvents() { ... deliverInputEvent(q); ... } private void deliverInputEvent(QueuedInputEvent q) { InputStage stage; if (q.shouldSendToSynthesizer()) { stage = mSyntheticInputStage; } else { stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage; } if (stage != null) { handleWindowFocusChanged(); stage.deliver(q); } else { finishInputEvent(q); } } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } }
在onInputEvent中会调用enqueueInputEvent(),scheduleProcessInputEvents最初也会doProcessInputEvents()
InputStage 一个解决解决Input Event的责任链基类;在ViewRootImpl的setView中有设置
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;
stage.deliver(q);中事件会传递到ViewPostImeInputStage的onProcess办法
咱们重点关注下:ViewPostImeInputStage
public ViewPostImeInputStage(InputStage next) { super(next); } @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); } } }}
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent; boolean handled = mView.dispatchPointerEvent(event); return handled ? FINISH_HANDLED : FORW }
这里的mView就是DecorView,是在调用setView时候赋值的,由此事件传递到了DecorView
View的办法
@UnsupportedAppUsage
public final boolean dispatchPointerEvent(MotionEvent event) { if (event.isTouchEvent()) { return dispatchTouchEvent(event); } else { return dispatchGenericMotionEvent(event); } } //DecorView的办法 @Override public boolean dispatchTouchEvent(MotionEvent ev) { //cb就是activity 在Activity的attach中设置mWindow.setCallback(this); final Window.Callback cb = mWindow.getCallback(); return cb != null && !mWindow.isDestroyed() && mFeatureId < 0 ? cb.dispatchTouchEvent(ev) : super.dispatchTouchEvent(ev); } //activity的办法 public boolean dispatchTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { onUserInteraction(); } if (getWindow().superDispatchTouchEvent(ev)) { return true; } return onTouchEvent(ev); } //事件从新到了DecorView @Override public boolean superDispatchTouchEvent(MotionEvent event) { return mDecor.superDispatchTouchEvent(event); } //DecorView public class DecorView extends FrameLayout public boolean superDispatchTouchEvent(MotionEvent event) { return super.dispatchTouchEvent(event); }
DecorView是FrameLayout的子类,事件传递到了咱们相熟的ViewGroup