本文主要学习记录,基于Android 10的源码,有错误欢迎指正,主要目的是梳理流程图。
以进程为单位的调用栈图如下:
1activity中的startActivity方法最终都会通过拿到ATSM的代理IActivityTaskManager调用的startActivity;
2之后进入system server进程中的ATMS startActivity,ATMS 经过收集Intent信息,然后使用ActivityStackSupervisorstartSpecificActivityLocked,如果进程已经存在,则直接使用realStartActivityLocked,通过App的binder客户端的代理ApplicationThread调用回到bindApplication,走入Activity的启动流程;如果进程不存在则通过socket链接Zygote,请求fork新的进程;
3App进程创建完成后,进程启动会调用ActivityThreadmain方法,初始化主线程Handler,接着走入attach方法,然后通过AMS的代理调用AMS的attachApplication方法,并将App进程的通信代理ApplicationThread传入AMS;
4AMS获取到ATMS调用ApplicationThread的bindApplication回到App进程的ActivityThreadApplicationThreadbindApplication方法中,然后使用Handler切换到主线程执行handleBindApplication,这里初始化了App的进程名字、时间,用户的硬件配置,包括App的文件系统,创建了App的Context实例,Instrumentation实例,调用App的onCreate回调方法,同时告诉AMS APP初始化工作完毕;
5AMS接着会调用ATMS的attachApplication,最后调用ClientLifecycleManager的scheduleTransaction方法,通过App的Binder代理ApplicationThread回到ActivityThread;
6进入ActivityThreadApplicationThreadscheduleTransaction方法之后就进入了Activity的onStart、onResume回调
创建进程之前的过程主要是AMS的内部信息收集的判断的过程,下面主要看一下App进程启动的源码流程
从应用进程被创建开始,ActivityThreadmain被执行
调用ActivityThread的attach方法,然后将activity和AMS通信的Binder代理IApplicationThread实例传入AMS
接着进入AMS进程,ActivityManagerServiceattachApplicationLocked
1threadbindApplication :该方法主要讲App进程的配置信息通过IApplicationThread Binder通信回传到ActivityThread中
2mAtmInternalattachApplication :mAtmInternal实际就是ActivityTaskManager的实例,通过LocalServices加载
那么这里相当于走到了ActivityTaskManagerServer的attachApplication中
先看第一条:
注意:ActivityThread中存在于Binder通信的代理--》ApplicationThread extends IApplicationThreadStub
ActivityThread--》ApplicationThread--》bindApplication
这里的bindApplication主要初始化了AppBindData,然后发送BIND_APPLICATION给APP的主线程BIND_APPLICATION,最后执行了handleBindApplication
handleBindApplication如下:
ActivityThread--》class H extends Handler
该方法主要在App进程中对App的一些硬件资源配置申请的属性、App的文件夹等完成App基本信息的初始化
接着看第二条:mAtmInternalattachApplication
mAtmInternalattachApplication最终会调用mRootActivityContainerattachApplication(wpc)
RootActivityContainerattachApplication
接着调用ActivityStackSupervisorrealStartActivityLocked开始创建Activity
ActivityStackSupervisorrealStartActivityLocked
创建ClientLifecycleManager和ClientTransactionHandler来辅助管理Activity的生命周期
注意
clientTransactionaddCallback是LaunchActivityItem
lifecycleItem是ResumeActivityItem
ClientLifecycleManagerscheduleTransaction最终会调用ClientTransaction的schedule方法
那么这个mClient是IApplicationThread的实例,那么此时也就回到了ActivityThread的ApplicationThread中
ActivityThread的ApplicationThread中
因为ActivityThread继承ClientTransactionHandler,所以到了ClientTransactionHandler中
通过Handler发送消息EXECUTE_TRANSACTION到H中
接着TransactionExecutor的execute方法
LaunchActivityItemexecute方法
client其实是在ActivityThread的实例,那么就回到了ActivityThread的handleLaunchActivity
接着调用performLaunchActivity
在performLaunchActivity中,主要是加载App的资源包,然后创建了Activity的context实例,并创建了Activity的实例,接着调用activityattach方法,attach执行完之后调用了onCreate方法。
activityattach
activityattach中主要
1创建了PhoneWindow实例
2设置了Window接口的监听
3初始化了成员变量,包括线程和WindowManager
到此Oncreate已经完成,那么OnStart和OnResume去哪了?
TransactionExecutor的execute方法
之前们只分析了executeCallbacks,接着executeLifecycleState方法
TransactionExecutor的executeLifecycleState方法
cycleToPath:lifecycleItem即为ResumeActivityItem
第一点:
int finish = lifecycleItemgetTargetState()
lifecycleItem对应ResumeActivityItem,如下:
ResumeActivityItem的getTargetState方法
对应ActivityLifecycleItem中的枚举类型:
第二点:ActivityClientRecord中的mLifecycleState,由于在前面已经执行了handleLaunchActivity所以mLifecycleState=1
对应ActivityLifecycleItem中的枚举类型:
PRE_ON_CREATE = 0
所以final int star = 1
接着看getLifecyclePath,此时start=1,finish=3
那么返回的IntArray就是2
接着看performLifecycleSequence
最终执行的是handleStartActivity所以最终走到了ActivityThread的handleResumeActivity
两点:
调用activityperformStart
调用InstrumetationcallActivityOnPostCreate
performStart方法:
调用了InstrumentationcallActivityOnStart方法:
最终到了activity的onStart方法
第二点:InstrumentationcallActivityOnPostCreate
上面主要走了cycleToPath,接着ResumeActivityItemexecute
调用了handleResumeActivity方法
handleResumeActivity最终调用performResumeActivity
调用了InstrumentationcallActivityOnResume,
到了activityonResume()方法
参考文章: >
要启动一个新的Activity,我们可以通过调用Context中的startActivity来启动。像这样:
Intent intent = new Intent(this, ActivityDemoclass);
startActivity(intent); // ActivityDemo是需要启动的Activity类
通过上面的方法可以启动新的Activity了,但如果我要从当前的Activity中传递数据到新的Activity呢?很简单:Intent intent = new Intent(this,ActivityDemoclass);
Bundle bundle = new Bundle();
bundleputBoolean("bool_key", true);
intentputExtras(bundle);
startActivity(intent);
还有,有时候我们需要启动带返回值的Activity,简单的说就是需要新启动的Activity返回时将值传递给启动它的Activity,像这样:
Intent intent = new Intent(ActivityLifeDemothis,RevalueActivityclass);
startActivityForResult(intent, 0x1001);
ActivityLifeDemo是当前的Activity,启动RevalueActivity,我们在ActivityLifeDemo中需要获取RevalueActivity传回来的值。那么在RevalueActivity中就必须这样写:
Intent intent = new Intent();
intentputExtra("revalue_key","haha-revalueActivity");
setResult(0x1001, intent);
那么“revalue_key”值在哪里获取呢?必须重写onActivityResult方法,通过判断requestCode,来确定
if(requestCode==0x1001){
String str = datagetStringExtra("revalue_key");
Logi(TAG, "返回的值为:"+str);
}
1 从 Activity 本地调用startActivity()--> Activity#startActivityForResult()
2 Instrumentation #execStartActivity:Instrumentation类相当于一个管家,它的职责是管理各个应用程序和系统的交互,Activity都有此对象的实际引用,可以通过它监测系统与应用程序之间的所有交互。
3 ActivityManagerProxy #startActivity():发起了一次跨进程调用,ActivityManagerService是ActivityManagerNative的具体实现。
4 ActivityStarter ():主要负责处理Activity的Intent和Flags, 还有关联相关的Stack和TaskRecord。
ActivityStackstartActivityMayWait():获取Activity的启动信息,包括ResolveInfo和ActivityInfo,以及获取CallingPid和CallingUid;
ActivityStackstartActivityLocked():创建一个ActivityRecord;
ActivityStackstartActivityUnchecked():设置TaskRecord, 完成后执行ActivityStackSupervisor类的resumeFocusedStackTopActivityLocked方法
5 ActivityStackSupervisor 和 ActivityStack :这里会判断进程是否存在和一些生命周期的方法
ActivityStackSupervisor#resumeFocusedStackTopActivityLocked()
--> ActivityStackSupervisor#resumeTopActivityUncheckedLocked():
--> ActivityStack#resumeTopActivityInnerLocked()
--> ActivityStackSupervisor#startSpecificActivityLocked()
6: ApplicationThread :IApplicationThread的直接实现,发起了一次跨进程调用
7: ActivityThread :会调用sendMessage,最后调用到mHsendMessage(msg);
8: ActivityThread # performLaunchActivity ():会收集要启动的Activity的相关信息,主要是package和component信息,然后通过ClassLoader将要启动的Activity类加载出来。最后调用mInstrumentationcallActivityOnCreate()
9: Activity # performStart ():Activity的生命周期方法是通过Instrumentation类调用callActivityOnXXX方法最终调用Activity的onCreate等方法,调用时机为ActivityThread#performLaunchActivitiy()方法中。
一 应用程序的MainActivity通过Binder进程间通信机制通知ActivityManagerService,它要启动一个新的Activity;
二 ActivityManagerService通过Binder进程间通信机制通知MainActivity进入Paused状态;
三 MainActivity通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就准备要在MainActivity所在的进程和任务中启动新的Activity了;
四 ActivityManagerService通过Binder进程间通信机制通知MainActivity所在的ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动 *** 作了。
Instrumentation : 监控应用与系统相关的交互行为。
AMS :组件管理调度中心,什么都不干,但是什么都管。
ActivityStarter :处理Activity什么时候启动,怎么样启动相关问题,也就是处理Intent与Flag相关问题,平时提到的启动模式都可以在这里找到实现。
ActivityStackSupervisior :这个类的作用你从它的名字就可以看出来,它用来管理Stack和Task。
ActivityStack :用来管理栈里的Activity。
ActivityThread :最终干活的人,是ActivityThread的内部类,Activity、Service、BroadcastReceiver的启动、切换、调度等各种 *** 作都在这个类里完成。
当目标Activity所属的进程已创建,则下一步调用到ATscheduleResumeActivity;
当目标Activity所属的进程未创建,则先创建进程后,再调用ATscheduleLaunchActivity
将Window相应task移至顶部,并创建AppWindowToken对象
创建LoadedApk对象;
创建ComponentName对象;
获取ClassLoader;
创建目标Activity对象;
创建Application对象;
回调onCreate(),一般地该方法内执行setContentView() *** 作;
获取activity的WindowManager
把actvitity的decorview设置INVISIBLE添加上去addview->mWindowSessionaddToDisplay->WMSaddWindow
makeVisible
activityResumed
updateFocusedWindowLocked来更新聚焦窗口情况
AMS通过binder最终通知ApplicationThread,进而通知主线程,ActivityThread通过HhandleMessage()来控制Activity的生命周期。
ActivityThreadhandleConfigurationChanged
ApplicationonCreate
ActivityonCreate
ActivityonRestoreInstanceState
ActivityonRestart
ActivityonStart
ActivityonResume
ActivityonRestart
ActivityonStart
ActivityonResume
ActivityonSaveInstanceState
ActivityonPause
ActivityonSaveInstanceState
ActivityonStop
trimApplications() kill空进程并且更新进程的Adj值
ActivityonDestroy
检查第一个没有结束的activity 如没有显示launcher
ActivityonPause
ActivityonNewIntent
ActivityonRestart
ActivityonStart
ActivityonResume
一先理解栈的概念(放置Activity实例的容器)
1Task(线性表)
任务栈Task,用来放置Activity实例的容器,先进后出,主要有2个基本 *** 作:压栈和出栈,其所存放的Activity是不支持重新排序的, 只能根据压栈和出栈 *** 作更改Activity的顺序 。
2app启动时,系统会为它默认创建一个对应的Task,用来放置根Activity
ps: Activity之间可以相互启动,当前应用的Activity可以去启动其他应用的Activity(相机),那么就是说栈的功能可以把其它app的activity加入到自己app的栈里
所以Task可以理解为负责管理所有用到的Activity实例的栈,但是android50之后 跨进程调用activity,这个activity会被放入到一个新的栈中。
二启动模式(只能根据压栈和出栈 *** 作更改Activity的顺序,所以是启动模式是以哪种姿势入栈)
通过在AndroidManifest文件中的属性andorid:launchMode来设置或者通过Intent的flag来设置
1standard(常规姿势入栈)
默认模式。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。应用场景:绝大多数Activity。
2singleTop(栈顶复用姿势入栈)==FLAG_ACTIVITY_SINGLE_TOP
栈顶复用模式,如果要开启的activity在任务栈的顶部已经存在,就不会创建新的实例,而是调用 onNewIntent() 方法。避免栈顶的activity被重复的创建。应用场景:在通知栏点击收到的通知,然后需要启动一个Activity,这个Activity就可以用singleTop,否则每次点击都会新建一个Activity。某个场景下连续快速点击,启动了两个Activity。如果这个时候待启动的Activity使用 singleTop模式也是可以避免这个Bug的。
3singleTask(栈内复用姿势入栈)==FLAG_ACTIVITY_CLEAR_TOP
栈内复用模式, activity只会在任务栈里面存在一个实例。如果要激活的activity,在任务栈里面已经存在,就不会创建新的activity,而是复用这个已经存在的activity,调用 onNewIntent() 方法,并且清空这个activity任务栈上面所有的activity( CLEAR_TOP回到栈顶 )。应用场景:大多数App的主页。对于大部分应用,当我们在主界面点击回退按钮的时候都是退出应用,那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能报销毁。
4singleInstance(不入栈)
单一实例模式,整个手机 *** 作系统里面只有一个实例存在。不同的应用去打开这个activity 共享公用的同一个activity。他会运行在自己单独,独立的任务栈里面,并且任务栈里面只有他一个实例存在。应用场景:呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。建议谨慎使用。
5FLAG_ACTIVITY_NO_HISTORY
Activity使用这种模式启动Activity,当该Activity启动其他Activity后,该Activity就消失了,不会保留在Activity栈中。
1getTaskId();获取当前activity所处的栈
2同一个应用程序中的activity的亲和性一样(taskAffinity),也就是说 Actviitya intent时setFalg(IntentFLAG_ACTIVITY_NEW_TASK)到Activityb 但是Actviitya和Activityb 还是一个栈
在不同的应用中跳转才会创建新的Task。
3在Activity上下文之外启动Activity需要给Intent设置FLAG_ACTIVITY_NEW_TASK标志,不然会报异常。
四 FLAG_ACTIVITY_CLEAR_TASK(必须和FLAG_ACTIVITY_NEW_TASK一起使用)
清空栈内activity,只留下这个activity
在目的activity中获取intent启动源的名字的方法
1 先说在setClass启动一个Activity的方法吧:
Intent intent = new Intent();
intentsetClass(this, CreatePlaylistclass) //参数一为当前Package的context,t当前Activity的context就是this,其他Package可能用到createPackageContex()参数二为你要打开的Activity的类名
startActivity(intent);
2 通过Component Name来打开的方式
Intent intent = new Intent();
intentsetAction(IntentACTION_MAIN); //添加一些特性,具体可以查看Intent文档,相关属性的介绍
intentaddCategory(IntentCATEGORY_LAUNCHER);
intentsetFlags(IntentFLAG_ACTIVITY_NEW_TASK | IntentFLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
//通过Bundle向要打开的的Activity传递一些数据
Bundle bundle = new Bundle();
bundleputString("data", new String(" Hello World"));
intentputExtras(bundle);
intentsetComponent(new ComponentName(
new String("comandroidtestActivity"), new String("comandroidtestActivitytestActivity")));
startActivity(intent);
当一个应用程序的Activity很多的时候,为了更好的用户体验效果,就需要对Activity的显示顺序做一些人为控制,而不要使用Android自身的Activity的历史记录堆栈机制,此时常常需要知道上一个Activity是哪一个。具体做法思路就是通过Intent启动一个Activity时,把当前的Activity信息传递到下一个Activity中,当下一个Activity启动时,通过Intent获取传入的参数即可知道上一个Activity的信息。
以上就是关于Android 10.0 Activity的启动流程全部的内容,包括:Android 10.0 Activity的启动流程、关于安卓intent启动activity的几种情况、如何启动一个activity涉及到哪些方法等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)