慕课网 剖析framework 笔记
4-1 说说Activity的启动流程
考察:
1,启动Activity经历哪些声明周期回调
2,冷启动流程,涉及的组件,组件通信过程是怎么样的
3,Activity启动过程中,生命周期回调的原理
1,Activity的启动原理:
1)startActivity:
这个要跨进程调用到AMS,为什么?
因为Activity是应用组件,启动本地线程没人管你,但是启动应用组件要向AMS报告的,
2)发请求给AMS:
ActivityManagerNative.getDefault().startActivity //拿到AMS的代理对象
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0); //通过transact发请求,请求码是START_ACTIVITY,
transact就是把所有的请求参数data封装到parcel里面,再写到binder驱动,binder驱动转发给AMS,AMS就收到了onTransact回调,
再把请求参数data取出来,再通过code请求码处理请求
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags){
switch(code){
case START_ACTIVITY_TRANSACTION:{
//走到了AMS的startActivity
startActivity(app, callingPackage, intent, ...);
}
...
}
}
TRANSACTION:{ //走到了AMS的startActivity startActivity(app, callingPackage, intent, ...); } ... } }
看看AMS的startActivity怎么处理:
void startSpecificActivityLocked(ActivityRecord r,...){
//查询Activity对应的进程是否已经启动,
ProcessRecord app = mService.getProcessRecordLocked(r.processName, ...);
//看进程对应的ProcessRecord是不是存在,再看看AP是否向AMS注册过自己的application thread,
if(app != null && app.thread != null){
//都满足则真正启动Activity
realStartActivityLocked(r, app, ...);
return;
}
//不满足,先启动进程,再回头处理Activity的启动,也是用的readStartActivityLocked
mService.startProcessLocked(r.processName, ...);
}
看看startProcessLocked()函数
private final void startProcessLocked(ProcessRecoed app,){
//entryPoint是AP进程启动后,入口函数的java类,
if(entryPoint == null) entryPoint = "android.app.ActivityThread";
//Process.start会向zygote发送一个启动进程的请求,
//参数带了entryPoint,这样zygote就知道进程启动后要执行哪个java类的入口函数
//返回进程的pid,放在ProcessStartResult里面
Process.ProcessStartResult startResult = Process.start(entryPoint,);
synchronized(mPidsSelfLocked){
//往map里添加记录,key是pid,value是AP对应的ProcessRecord,
mPidsSelfLocked.put(startResult.pid, app);
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
//延时发送消息,10s内不向AMS报告就超时,AMS就清理这个AP相关的信息,如启动的应用组件。
mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
}
}
public static final ProcessStartResult start(final String processClass,){
return startViaZygote(processClass,);
}
//startViaZygote做了两件事
ProcessStartResult startViaZygote(final String processClass,){
//2,通过socket发送启动进程参数,再读取返回结果
return zygoteSendArgsAndGetResult(
//1,打开通过zygote的socket
openZygoteSocketIfNeeded(abi), argsForZygote);
}
//看看zygote端的处理
boolean runOnce(){
//读取参数列表,创建子进程
String[] args = readArgumentList();
int pid = Zygote.forkAndSpecialize(...);
if(pid == 0){
//子进程,1,通用init:如启动binder机制,
//2,执行AP的入口函数,就是ActivityThread的main函数
handleChildProc(parsedArgs,);
reutrn true;
}else{
//父进程,把子进程的pid通过socket返回给AMS
return handleParentProc(pid,);
}
}
看看AP的入口函数,就是ActivityThread的main函数
public static void main(String[] args){
//准备好主线程的looper
Looper.prepareMainLooper();
//创建ActivityThread对象,它的构造函数没什么特别的
ActivityThead thread = new ActivityThread();
//关键是这个attach函数,它要向AMS注册了,
//周期说过,AMS向zygote发进程启动请求后,会等待AP向它报告,超过10s就清理AP
//attach就是要向AMS报道的,看看attach的实现:
thread.attach(false);
Looper.loop();
thwor new RuntimeException("Main thread loop unexpectedly exited");
}
//attach的实现其实是一个跨进程调用,
private void attach(boolean system){
//拿到AMS的binder对象,
IActivityManager mgr = ActivityManagerNative.getDefault();
//参数是AP端的binder对象,是ApplicationThread类型的,这样AMS拿到后就可以调到AP端了,
mgr.attachApplication(mAppThread);
}
总结:
1,AMS通过socket向zygote进程发出启动AP进程的请求,
2,zygote收到后启动AP进程,
3,AP的入口函数是ActivityThread的main,然后里面会调AMS的attachApplication,把AP自己的ApplicationThread的binder句柄注册给AMS,便于只有与AMS双向调用。
看看AMS的attachApplication做了什么:
boolean attachApplicationLocked(IApplicationThread thread, int pid){
//通过pid,在map里面查对应的ProcessRecord,
ProcessRecord app = mPidsSelfLocked.get(pid);
//thread是AP端注册到AMS的binder对象,是Application thread类型的
//bindApplication让AP端做一些init,如创建Application,它会调到AP进程里面
thread.bindApplication(...);
//下面3个,处理挂起的一些应用组件,因为进程没启动,所以挂起了。现在进程启动了,可以启动他们了。
//这是关于Acitivity的
mStackSupervisor.attachApplicationLocked(app);
.....
//关于Service
mSerices.attachApplicationLocked(app, processName);
.....
//关于广播
sendPendingBroadcastsLocked(app);
}
看看关于Activity的处理
boolean attachApplicationLocked(ProcessRecord app){
...
//拿到一个stack,这个stack是mFocusedStack,
//AMS中有两个stack,一个是launcher的,一个是mFocusedStack,AP的task都归mFocusedStack管,
//从stack里面找到最近的task,从task取出栈顶的activity,
//这里的hr就是要启动的Activity,之前因为进程没启动,所以耽搁了,但其实数据结构已经加好了,就等待启动了。
ActivityRecord hr = stack.topRunningActivityLocked(null);
//拿到准备好的ActivityRecord,启动Activity。
realStartActivityLocked(hr, app, true, true);
...
}
看看realStartActivityLocked的实现
final boolean realStartActivityLocked(ActivityRecord r,){
//app是ProcessRecord,对应AP进程,
//thread对应ApplicatoinTHread binder对象,是AP进程启动时注册到AMS的,
//现在AMS通过这个binder对象向AP发送binder调用,scheduleLaunchActivity,要在AP端执行,意思是AP可以开始加载Activity了。
app.thread.scheduleLaunchActivity(new Intent(r.intent),...);
...
}
看看AP如何处理这个binder调用:scheduleLaunchActivity
@Override
public final void scheduleLaunchActivty(Intent intent, IBinder token,){
//AP收到请求,没有立刻处理,而是封装了一个消息,再sendMessage丢给主线程,
ActivityClinetRecord r = new ActivityClientRecord();
...
//丢到mH,main handler,主线程的handler,
sendMessaage(H.LAUNCH_ACTIVITY, r);
}
看看主线程如何处理
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
//生成一个LoadedApk对象,保存了AP的APK信息,
//因为之后创建Acitivity的时候要用到classloaded去加载APK的Activity类,所以这里先准备好,
r.packageInfo = getPackageInfoNoCheck(...);
handleLaunchActivity(r. null);
//handleLaunchActivity,是真正创建Activity回调生命周期的时候,分两部分做
private void handleLaunchActivity(ActivityClientRecord r,...){
//1,performLaunchActivity
Activity a = performLaunchActivity(r,customIntent);
if(a != null){
//2,
handleResumeActivity(r.token, false,...);
}
}
1,
private Activity performLaunchActivity(ActivityClientRecord r,...){
//创建Activity对象
Activity activity = mInstrumentation.newActivity(...);
//其实Appliccation在AP启动时已经创建好了,这里只是返回而已
Application app = r.packageInfo.makeApplication(false,mInstrumentation);
//创建context,new了一个ContextImpl对象,然后把context attach给Activity,里面也有一些Activity的init工作。
Context appContext = createBaseContextForActivity(r, activity);
activity.attach(appContext, ...);
//调到Activity的生命周期,onCreate回调
mInstrumentation.callActivityOnCreate(activity, r.state);
//调用Activity的onStart回调,
activity.performStart();
return activity;
}
2,
final void handleResumeActivity(IBinder token,){
ActivityClientRecord r = performResumeActivity(...);
}
performResumeActivity() => r.activiyt.performResumer() =>
mInstrumentation.callActivityOnResume(this) => activity.onResume()
总结,AP端,Activity启动的步骤:
1)创建Activity对象(通过classLoader加载APK里面的Activity类,生成Activity对象)
2)准备好Application(不是创建Application,因为它在AP进程启动时已经创建好了,这里返回就行了)
3)创建ContextImpl
4)attach context,(也包括与Activity运行有关的重要系统变量)
5)执行生命周期回调
总结:Activity启动过程涉及的组件的通信过程:
1,首先向AMS发起startActivity请求,
2,AMS发现AP进程没有启动,通过socket向zygote发起启动AP进程的请求,
3,AP启动后,向AMS发起attachApplication的IPC调用,它是为了在AMS注册AP里的ApplicatoinThread,
4,AMS向AP发起bindApplication IPC调用,它用来给AP init Application的
5,AMS向AP发起scheduleLaunchActivity的IPC调用,用来给AP加载和创建Activity。并且执行Activity的生命周期的,
总结:述说Activity的启动流程
1,启动Activity不是本地行为,要AMS参与的,需要向AMS发起binder调用,
2,Activity所在进程是怎么启动的?zygote和AP之间的通信过程等
3,AP启动后,AP段的Activity是如何init的,生命周期如何回调的。