Android framework : Activity启动流程

慕课网 剖析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的,生命周期如何回调的。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值