CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
attachBaseContext(context);
mFragments.attachHost(null /parent/);
//PhoneWindow初始化
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(mWindowControllerCallback);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
2.ActivityThread.handleResumeActivity() 通过PhoneWindow获取DecorView,然后调用activity.makeVisible()
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
…
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
…
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
a.onWindowAttributesChanged(l);
}
}
} else if (!willBeVisible) {
if (localLOGV) Slog.v(TAG, “Launch " + r + " mStartedActivity set”);
r.hideForNow = true;
}
…
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
…
}
2.1 PhoneWindow创建DecorView的过程
@Override
public final @NonNull View getDecorView() {
if (mDecor == null || mForceDecorInstall) {
//组装DecorView
installDecor();
}
return mDecor;
}
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
//获取DecorView
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
}
//返回值就是DecorView
protected DecorView generateDecor(int featureId) {
// System process doesn’t have application context and in that case we need to directly use
// the context we have. Otherwise we want the application context, so we don’t cling to the
// activity.
Context context;
if (mUseDecorContext) {
Context applicationContext = getContext().getApplicationContext();
if (applicationContext == null) {
context = getContext();
} else {
context = new DecorContext(applicationContext, this);
if (mTheme != -1) {
context.setTheme(mTheme);
}
}
} else {
context = getContext();
}
return new DecorView(context, featureId, this, getAttributes());
}
2.2. activity.makeVisible()过程
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
//此时调用的其实事WindowManager.addView()
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
3. WindowManager是接口,找到其实现类并调用WindowManagerImpl.addView()
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
//此时调用的是WindowManagerGlobal.addView()
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
mContext.getUserId());
}
4. WindowManagerGlobal.addView() 初始化ViewRootImpl,然后调用root.setView()
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
…
synchronized (mLock) {
…
//初始化ViewRootImpl
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) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
5. ViewRootImpl.setView(view,…,…) 创建InputChannel, InputQueue, WindowInputEventReceiver
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {
synchronized (this) {
if (mView == null) {
mView = view;
…
// Schedule the first layout -before- adding to the window
// manager, to make sure we do the relayout before receiving
// any other events from the system.
requestLayout();
InputChannel inputChannel = null;
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
inputChannel = new InputChannel();
}
if (inputChannel != null) {
if (mInputQueueCallback != null) {
//创建对象
mInputQueue = new InputQueue();
mInputQueueCallback.onInputQueueCreated(mInputQueue);
}
mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
Looper.myLooper());
}
}
}
6. 其实Android事件的源头来自于用户输入行为,由硬件进行捕获,一般会保存在 dev/input 节点下,后续组装成KeyEvent/MotionEvent对象,经Native进入Java的InputEventReceiver.dispatchInputEvent()中。
我们先分析InputEventReceiver
private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event);
}
public void onInputEvent(InputEvent event) {
finishInputEvent(event, false);
}
由于InputEventReceiver是abstract类,因此需要找到对应的实现类,此时第5步中 WindowInputEventReceiver 即是实现类,因此找到重写的onInputEvent()方法进行下一步分析。
7. ViewRootImpl.WindowInputEventReceiver extends InputEventReceiver,连带调用了enqueueInputEvent()->doProcessInputEvents-> deliverInputEvent(q),方法中获取到mFirstPostImeInputStage对象其实为ViewPostImeInputStage。
@Override
public void onInputEvent(InputEvent event) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, “processInputEventForCompatibility”);
List 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);
// Always enqueue the input event in order, regardless of its time stamp.
// We do this because the application or the IME may inject key events
// in response to touch events and we want to ensure that the injected keys
// are processed in the order they were received and we cannot trust that
// the time stamp of injected events are monotonic.
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 {
scheduleProcessInputEvents();
}
}
void doProcessInputEvents() {
// Deliver all pending input events in the queue.
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);
}
// We are done processing all input events that we can process right now
// so we can clear the pending flag immediately.
if (mProcessInputEventsScheduled) {
mProcessInputEventsScheduled = false;
mHandler.removeMessages(MSG_PROCESS_INPUT_EVENTS);
}
}
private void deliverInputEvent(QueuedInputEvent q) {
…
try {
…
InputStage stage;
if (q.shouldSendToSynthesizer()) {
stage = mSyntheticInputStage;
} else {
//此时返回两个InputStage类型的对象,这个InputStage为abstract因此需要找对应的实现类。
stage = q.shouldSkipIme() ? mFirstPostImeInputStage : mFirstInputStage;
}
if (q.mEvent instanceof KeyEvent) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, “preDispatchToUnhandledKeyManager”);
try {
mUnhandledKeyManager.preDispatch((KeyEvent) q.mEvent);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
if (stage != null) {
handleWindowFocusChanged();
stage.deliver(q);
} else {
finishInputEvent(q);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
此时需要注意这个InputStage 的实现类相对比较多,不过可以重点看下setView()方法的末尾,着重看mFirstPostImeInputStage赋值逻辑。
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView, int userId) {
…
// Set up the input pipeline.
CharSequence counterSuffix = attrs.getTitle();
mSyntheticInputStage = new SyntheticInputStage();
//最终new了ViewPostImeInputStage
InputStage viewPostImeStage = new ViewPostImeInputStage(mSyntheticInputStage);
//继续看viewPostImeStage赋值
InputStage nativePostImeStage = new NativePostImeInputStage(viewPostImeStage,
“aq:native-post-ime:” + counterSuffix);
//初始化并传入nativePostImeStage,需要查看nativePostImeStage赋值逻辑,继续往上看。
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;
//这是赋值位置,可以看以上逻辑是怎么赋值earlyPostImeStage对象
mFirstPostImeInputStage = earlyPostImeStage;
mPendingInputEventQueueLengthCounterName = “aq:pending:” + counterSuffix;
if (mView instanceof RootViewSurfaceTaker) {
PendingInsetsController pendingInsetsController =
((RootViewSurfaceTaker) mView).providePendingInsetsController();
if (pendingInsetsController != null) {
pendingInsetsController.replayAndAttach(mInsetsController);
}
}
}
通过以上逻辑可以清晰地看到mFirstPostImeInputStage 即是ViewPostImeInputStage,我们需要跟进ViewPostImeInputStage看下对应的onProcess()方法。
final class ViewPostImeInputStage extends InputStage {
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);
}
}
}
…
}
以上逻辑中先判断了输入事件是键盘,还是触摸,触摸逻辑中又判断了输入源是屏幕还是trackball(我猜测这判断的是鼠标等设备输入),不过不重要,我们主要看屏幕输入的逻辑,也就是processPointerEvent(q);方法
private int processPointerEvent(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent)q.mEvent;
mAttachInfo.mUnbufferedDispatchRequested = false;
《设计思想解读开源框架》
第一章、 热修复设计
-
第一节、 AOT/JIT & dexopt 与 dex2oat
-
第二节、 热修复设计之 CLASS_ISPREVERIFIED 问题
-
第三节、热修复设计之热修复原理
-
第四节、Tinker 的集成与使用(自动补丁包生成)
第二章、 插件化框架设计
-
第一节、 Class 文件与 Dex 文件的结构解读
-
第二节、 Android 资源加载机制详解
-
第三节、 四大组件调用原理
-
第四节、 so 文件加载机制
-
第五节、 Android 系统服务实现原理
第三章、 组件化框架设计
-
第一节、阿里巴巴开源路由框——ARouter 原理分析
-
第二节、APT 编译时期自动生成代码&动态类加载
-
第三节、 Java SPI 机制
-
第四节、 AOP&IOC
-
第五节、 手写组件化架构
第四章、图片加载框架
-
第一节、图片加载框架选型
-
第二节、Glide 原理分析
-
第三节、手写图片加载框架实战
第五章、网络访问框架设计
-
第一节、网络通信必备基础
-
第二节、OkHttp 源码解读
-
第三节、Retrofit 源码解析
第六章、 RXJava 响应式编程框架设计
-
第一节、链式调用
-
第二节、 扩展的观察者模式
-
第三节、事件变换设计
-
第四节、Scheduler 线程控制
第七章、 IOC 架构设计
-
第一节、 依赖注入与控制反转
-
第二节、ButterKnife 原理上篇、中篇、下篇
-
第三节、Dagger 架构设计核心解密
第八章、 Android 架构组件 Jetpack
-
第一节、 LiveData 原理
-
第二节、 Navigation 如何解决 tabLayout 问题
-
第三节、 ViewModel 如何感知 View 生命周期及内核原理
-
第四节、 Room 架构方式方法
-
第五节、 dataBinding 为什么能够支持 MVVM
-
第六节、 WorkManager 内核揭秘
-
第七节、 Lifecycles 生命周期
本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
第二节、OkHttp 源码解读 -
第三节、Retrofit 源码解析
[外链图片转存中…(img-PzQ1Moay-1715418930312)]
第六章、 RXJava 响应式编程框架设计
-
第一节、链式调用
-
第二节、 扩展的观察者模式
-
第三节、事件变换设计
-
第四节、Scheduler 线程控制
[外链图片转存中…(img-lHsMX35U-1715418930312)]
第七章、 IOC 架构设计
-
第一节、 依赖注入与控制反转
-
第二节、ButterKnife 原理上篇、中篇、下篇
-
第三节、Dagger 架构设计核心解密
[外链图片转存中…(img-21SIzr69-1715418930313)]
第八章、 Android 架构组件 Jetpack
-
第一节、 LiveData 原理
-
第二节、 Navigation 如何解决 tabLayout 问题
-
第三节、 ViewModel 如何感知 View 生命周期及内核原理
-
第四节、 Room 架构方式方法
-
第五节、 dataBinding 为什么能够支持 MVVM
-
第六节、 WorkManager 内核揭秘
-
第七节、 Lifecycles 生命周期
[外链图片转存中…(img-tEAo21qN-1715418930313)]
本文包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…
[外链图片转存中…(img-eJljqjH7-1715418930314)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!