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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。