第三次 2个 消息:launch and resume
ActivityTaskSupervisor:
final ClientTransaction clientTransaction = ClientTransaction.obtain(
proc.getThread(), r.appToken);
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
//还有一个变量:mLifecycleStateRequest:ResumeActivityItem
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
第四次一个消息:TopResumedActivityChangeItem
ActivityTaskSupervisor:
ActivityRecord.scheduleTopResumedActivityChanged{
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
TopResumedActivityChangeItem.obtain(onTop));
}
第五个消息 : StopActivityItem
ActivityTaskSupervisor:
ActivityTaskSupervisor.activityIdleInternal>processStoppingAndFinishingActivities>
ActivityRecord.stopPossible{
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
StopActivityItem.obtain(configChangeFlags));
}
重点关注ActivityThread.handleXXX方法:
handleReLaunchActivity>
performDestroyActivity>
r.activity.retainNonConfigurationInstances();//保存 viewmodel等信息传递到新Activity
handleLaunchActivity>
unscheduleGcIdler();//取消在后台接受GC的消息
WindowManagerGlobal.initialize();//WMS 初始化
performLaunchActivity>
newActivity//反射创建 activity
makeApplicationif: (mApplication != null) return mApplication;
activity.attach>
attachBaseContext
new PhoneWindow()
if (theme != 0) {
activity. setTheme(theme) ;
}
if (r.isPersistable()) {// 区分持久化,调用onCreat
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
handleResumeActivity>
unscheduleGcIdler();
performResumeActivity>
activity.performResume>
dispatchActivityPreResumed//全局callback 回调
performStart/performRestart
mInstrumentation.callActivity OnResume (this);
mFragments.dispatchResume();
dispatchActivityPostResumed();全局callback 回调
if (r.window == null && !a.mFinished && willBeVisible) >//不考虑 onCreate中setContrentView触发了Window绑定
r.window = r.activity.getWindow();//PhoneWindow
View decor = r.window.getDecorView();
ViewManager wm = a.getWindowManager();//WindowManagerGlobal
wm.addView(decor, l)>//完成 viewRootImpl 与DecorView关联
Root = new ViewRootImpl()
root.setView(view:DecorView)>
requestLayout();//触发第一个粗略布局
Looper.myQueue().addIdleHandler(new Idler())>;//插入一条Idler消息
ac.activityIdle(a.token, a.createdConfig, stopProfiling)>//给所有没有
ActivityClientController.activityIdle>//ActivityClientController是一个 IBinder
activityIdleInternal>
mHandler.removeMessages( IDLE_TIMEOUT_MSG , r);
mHandler.removeMessages( LAUNCH_TIMEOUT_MSG );
processStoppingAndFinishingActivities>
if (r.isInHistory()) {
if ( r.finishing ) {
// TODO(b/137329632): Wait for idle of the right activity, not just any.
r.destroyIfPossible(reason);
} else {
r.stopIfPossible();>
}
}
.. r.destroyImmediately(reason);
r.stopIfPossible();>
mAtmService.getLifecycleManager().scheduleTransaction( StopActivityItem );
r.destroyImmediately(reason);>
mAtmService.getLifecycleManager().scheduleTransaction( DestroyActivityItem )
在resume之后发送idle消息,触发 stop
同时设置Idle超时消息,如果 10s没有执行则会主动再次触发 activityIdleInternal
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
StopActivityItem.obtain(configChangeFlags));
mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);//stop 超时时间 11s
mStopTimeoutRunnable:Slog.w(TAG, "Activity stop timeout for " + ActivityRecord.this);
notifyAppStopped();//应用停止运行
//如何取消stopTimeOut消息 需要去handleTopActivity看
关于 IdleHandler的执行时机
Looper.myQueue().addIdleHandler(new Idler())//mIdleHandlers.add()
MessageQueue.next()>MessageQueue:链表
每次根据时间查找满足执行的message
此次时间上没有要执行的message时,执行截至目前存在的全部Idle消息
轮训下一个时间可执行的消息
handleStopActivity
performStopActivityInner>
performPauseActivityIfNeeded //再次确认puase了没
callActivityOnStop>
callActivityOnSaveInstanceState // targetSdkVersion<28
activity.performStop>
dispatchActivityPreStopped
mFragments.dispatchStop()
mInstrumentation.callActivityOnStop
dispatchActivityPostStopped
callActivityOnSaveInstanceState(r) // targetSdkVersion>=28
if(targetSdkVersion>11){
QueuedWork.waitToFinish()//等待完成全部finish runnable
}
pendingActions.setStopInfo(stopInfo);//这里是重点
//-----如何回传到 ATMS 去 removeStopTimeOut消息的逻辑
TransactionExecutor中对所有的 ClientTransactionItem 调用
item.execute(mTransactionHandler:ClientTransactionHandler, token, mPendingActions);
item.postExecute(mTransactionHandler, token, mPendingActions);
回到 ActivityThread.reportStop(mPendingActions)>mH.post(pendingActions.getStopInfo());
执行 PendingTransactionActions.StopInfo 的run方法 通知ATMS
ActivityClient.getInstance().activityStopped(
mActivity.token, mState, mPersistentState, mDescription);
//binder:ActivityClientController>ActivityRecor.activityStopped>removeStopTimeOut
关于waitToFinish导致ANR的问题:在SharedPreferenceImpl中会调用 QueuedWork.addFinisher(sp 内存写入磁盘的runnable),单低于26(8.0)的SharedPreferenceImpl的实现性能较差,每次都是全部写入磁盘,有大量SP数据需要写入时,触发 finish 就会导致ANRq
handleDestroyActivity>
performDestroyActivity>
if (getNonConfigInstance) {r.lastNonConfigurationInstances = r.activity.retainNonConfigurationInstances()}
mInstrumentation.callActivityOnDestroy(r.activity);
cleanUpPendingRemoveWindows>
WindowManagerGlobal.closeAll()>
ViewRootImpl.die>
//解绑输入时间,销毁硬件渲染器,dispatchDetachedFromWindow,解绑 decorView
WindowManagerGlobal.getInstance().doRemoveView(this);//移除ViewRootImpl
事件:
第一块:接受native事件
WindowInputEventReceiver extends InputEventReceiver
Native>
InputEventReceiver.dispatchInputEvent>WindowInputEventReceiver.onInputEvent>ViewRootImpl.enqueueInputEvent>ViewRootImpl.doProcessInputEvents>....>processPointerEvent>View.dispatchPointerEvent>DecorView.dispatchTouchEvent>mWindow.CallBack.dispatchTouchEvent | super(ViewGroup).dispatchTouchEvent {Activity 可以截胡或消费后放行,但事件是从Native直接传递到ViewRootImpl的},
默认是走Activity dispatchTouchEvent,但会优先 回到View上,如果重写了可以自己截胡或者消费完再调super,只重写 onTouchEvent不重写dispatchTouchEvent 则在View消费后才有可能获取到事件
activity代码:
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) { // 这里的调用链条:IphoneWindow>mDecorView.superDispatchTouchEvent>ViewGroup.dispatchTouchEvent()
return true;
}
return onTouchEvent(ev);
}
Window.Callback.dispatchTouchEvent>Activity.dispatchTouchEvent>DOWN:onUserInteraction,Activity.onTouchEvent)
ViewGroup.dispatchTouchEvent>
第二块:ViewGroup
在Down事件或已有事件消费目标时
ViewGroup.disallowIntercept:false>ViewGroup.onInterceptTouchEvent
ViewGroup.disallowIntercept:true>intercepted = false
如果子view没有为父view设置DisallowIntercept,就查看父view自己是否在onInterceptTouchEvent自己拦截
第三块:ViewGroup if (!canceled && !intercepted) {}
未取消,父View也未拦截,处于初始事件,遍历childView 寻找消费目标:dispatchTransformedTouchEvent>addTouchTarget>
child.dispatchTouchEvent>realView.dispatchTouchEvent>onTouch | onTouchEvent
第四块:ViewGroup if(mFirstTouchTarget == null)
找不到消费目标丢给 父类:View.dispatchTouchEvent 处理
第五块:View
将后续事件传给上面找到的TargetView进行消费
布局:
第一块:onCreate:Activity的window 创建
ActivityThread.handleLaunchActivity>...>activit.attach>attachBaseContext,mWindow = PhoneWindow(ActivityClientRecord.mPendingRemoveWindow)
if(mPreserveWindow) mDecorView 将被复用否则 new PhoneWindow
UserActivity.setContentView>AppCompatActivity.setContentView>:initViewTreeOwners>getWindow().getDecorView
>PhoneWindow.getDecorView>PhoneWindow.installDecor>:createDecorView,mDecor.setWindow(this);
创建DecorView完成window与 DecorView的关联。DecorView父类是FrameLayout
DecorView创建时会出实话导航栏背景色,半透明状态栏颜色,导航栏进出动画等, AppCompatActivitysetContentView>:
getDelegate.setContentView>AppCompatDelegateImpl.setContentView>:ensureSubDecor()再次确保decorView已创建好
第二块:onResume
最后送福利了,现在关注我可以获取包含源码解析,自定义View,动画实现,架构分享等。
内容难度适中,篇幅精炼,每天只需花上十几分钟阅读即可。
大家可以跟我一起探讨,有flutter—底层开发—性能优化—移动架构—资深UI工程师 —NDK相关专业人员和视频教学资料,还有更多面试题等你来拿
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
你来拿**
[外链图片转存中…(img-0Gs5hVGv-1714125628544)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!