Android Framework系列5-1 Activity启

2021-03-04  本文已影响0人  无为3

Android 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函数

应用进程启动.png



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启动

总结

总结
上一篇下一篇

猜你喜欢

热点阅读