Android Framework系列5-1 Activity启
2021-03-04 本文已影响0人
无为3
Android Activity
本章主要围绕以下几点讲解:
- Activity冷启动原理
- 启动过程中涉及的组件及通信原理
- 启动过程中的生命周期回调原理
Activity冷启动原理
先从启动的入口函数看起:startActivity
// 代码来自Android23中:ContextImpl.java
public void startActivity(...){
mMainThread.getInstrumentation().execStartActivity(...);
}
// 代码来自Android23中:Instrumentation.java
public ActivityResult execStartActivity(...){
ActivityManagerNative.getDefault().startActivity(...);
}
跨进程调用,先通过ActivityManagerNative.getDefault()拿到AMS的代理对象(ActivityManagerProxy),调用它的startActivity()。
// 代码来自Android23中:ActivityManagerNative.java
class ActivityManagerProxy implements IActivityManager{
public int startActivity(...){
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
}
}
- 把所有的请求参数都封装到一个Parcel里面(参数data)
- 然后写到binder驱动,binder驱动再转发到AMS。
- 这样AMS就能收到一个onTransact回调。
// 代码来自Android23中:ActivityManagerNative.java
public abstract class ActivityManagerNative{
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags){
switch (code) {
case START_ACTIVITY_TRANSACTION: {
int result = startActivity(......)
}
......
}
}
现在着重看下AMS中怎么处理startActivity的,有点绕,我们就直接看关键的函数:
// 代码来自Android23中:ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r,...){
ProcessRecord app = mService.getProcessRecordLocked(...);
if (app != null && app.thread != null) {
realStartActivityLocked(r, app, andResume, checkConfig);
return;
}
mService.startProcessLocked(r.processName...)
}
看过我们前面章节的同学看到这块代码应该挺熟悉的,应用进程启动
- 查询Activity所属进程是否启动,也就是ProcessRecord对象不为空且应该用进程向AMS注册过IApplicationThread(app != null && app.thread != null)
- 如果上述条件成立,则直接启动Activity。
- 不成立再去启动进程。
进程启动
对startProcessLocked(进程启动)这个函数之前未做详细介绍,现在看看如何启动进程的:
// 代码来自Android23中:ActivityServiceManager.java
private final void startProcessLocked(ProcessRecord app,....){
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
Process.ProcessStartResult startResult = Process.start(entryPoint, );
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.put(startResult.pid, app);
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
}
}
- entryPoint这个就是应用进程启动之后,它的入口函数的java类。
- Process.start这个会向Zygote发送一个启动进程的请求,会把entryPoint带上,这样当Zygote启动进程后会知道启动那个java类的入口函数。
- 进程启动会返回ProcessStartResult,其中有进程的pid。
- 把进程app添加到mPidsSelfLocked(SparseArray类型),key为进程id。
- 延迟发送一个消息,代表应用进程启动之后在一定时间内(10秒内),没向AMS报告的话,就会超时,超时后AMS就会清理这个应用的所有信息。
继续深入看看Process.start做了什么事:
// 代码来自Android23中:Process.java
public static final ProcessStartResult start(...){
return startViaZygote(...);
}
// 代码来自Android23中:Process.java
ProcessStartResult startViaZygote(final String processClass,) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
startViaZygote这个函数做了两件事:
- 打开通往Zygote的Socket(通过openZygoteSocketIfNeeded)。
- 再通过socket发送启动进程的参数,然后读取返回结果(zygoteSendArgsAndGetResult)。
Zygote端的处理:
AMS向Zygote发送了socket消息,Zygote端如何处理呢?,具体看 应用进程启动 中的runOnce函数
Activity启动
前面讲到了,startActivity时如果进程未启动时是怎么启动进程的,现在来讲讲如果进程已经启动了,是怎么启动Activity的?还是看下关键函数:
// 代码来自Android23中:ActivityStackSupervisor.java
boolean attachApplicationLocked(ProcessRecord app){
ActivityRecord hr = stack.topRunningActivityLocked(null);
......
realStartActivityLocked(hr, app, true, true);
}
- 应用进程启动后,会去处理之前挂起的组件,Activity组件处理关键就是上面的attachApplicationLocked函数。
- stack是mFocusedStack:在AMS中有两个stack,一个是launcher的stack(跟桌面相关);还有一个就是非launcher的stack(mFocusedStack),我们应用的task都归mFocusedStack管。
- 拿到stack后会调用topRunningActivityLocked函数,找到最近的task取出栈顶的Activity,也就是我们要启动的Activity。
- realStartActivityLocked启动该Activity。
接着看下realStartActivityLocked函数:
// 代码来自Android23中:ActivityStackSupervisor.java
final boolean realStartActivityLocked(ActivityRecord r,...){
app.thread.scheduleLaunchActivity(...);
}
其中app就是ProcessRecord,thread就是应用端向AMS注册的binder句柄(IApplicationThread);scheduleLaunchActivity方法也就是在应用端ActivityTread中。
// 代码来自Android23中:ActivityThread.java
public final void scheduleLaunchActivity(...){
ActivityClientRecord r = new ActivityClientRecord();
......
sendMessage(H.LAUNCH_ACTIVITY, r);
}
// 代码来自Android23中:ActivityThread.java
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(.....);
handleLaunchActivity(r, null);
} break;
......
}
// 代码来自Android23中:ActivityThread.java
private void handleLaunchActivity(ActivityClientRecord r,......){
Activity a = performLaunchActivity(r, customIntent);
......
if (a != null) {
handleResumeActivity(r.token,......);
}
}
- 封装了一个启动Activity的消息,丢到主线程中。
- handler怎么处理消息呢:getPackageInfoNoCheck获取一个LoadedApk对象(应用的安装信息,之后创建activity需要用到ClassLoader去加载Apk中的Activity类)。
- 接下来就调用handleLaunchActivity,开始创建Activity生命周期。主要是两部分performLaunchActivity和handleResumeActivity。
handleResumeActivity这里就是调用了activity的onResume生命周期;再看看看看performLaunchActivity做了啥:
// 代码来自Android23中:ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, ...) {
Activity activity = mInstrumentation.newActivity(...);
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
Context appContext = createBaseContextForActivity(r, activity);
activity.attach(appContext, ...);
mInstrumentation.callActivityOnCreate(activity, r.state);
activity.performStart();
return activity;
}
- 先创建了一个Activity对象(也是通过ClassLoader newInstance)
- 创建Application(这个Application其实在进程启动后已经创建好了,这里只是返回这个Application对象)。
- 创建上下文Context,createBaseContextForActivity这里其实就是new了一个ContextImpl对象。
- activity.attach 把context赋给activity,也就是给activity创建了上下文。
- callActivityOnCreate其实就是调到了activity的onCreate生命周期回调。
- performStart其实就是调到了activity的onStart生命周期回调。
在应用端Activity启动流程总结:
Activity启动