Android启动流程分析(5)-Application和Activity的创建

App进程启动流程
回顾

上一篇文章的流程分析中可以看到,通过ActivityStack类去调用startSpecificActivity()方法的时候,会在ActivityStackSupervisor中判断进程是否存在,如果进程不存在会回调到AMS,通过AMS去给Zygote进程发送socket消息,zygote进程中,收到消息后就会去fork出新的应用进程,并反射执行ActivityThread.main()方法,这样一个app进程就在系统中运行了,接下来就要分析一下进程启动后的流程了

从入口函数ActivityThread.main()开始分析

//ActivityThread.java
public static void main(String[] args) {
//looper handler消息机制不是这篇文章分析的重点
       Looper.prepareMainLooper();
//创建ActivityThread并调用attach方法
       ActivityThread thread = new ActivityThread();
       thread.attach(false, startSeq);
       if (sMainThreadHandler == null) {
           sMainThreadHandler = thread.getHandler();
      }
       Looper.loop();
}

//thread.attach(false, startSeq);
private void attach(boolean system, long startSeq) {
         if (!system) {
           //拿到AMS对象
           final IActivityManager mgr = ActivityManager.getService();
           try {
               mgr.attachApplication(mAppThread, startSeq);
          }
      } 
}

final ApplicationThread mAppThread = new ApplicationThread();
private class ApplicationThread extends IApplicationThread.Stub {}

应用进程启动的入口函数main()方法中,会调用Looper相关的初始化和循环方法,从而让主线程的Looper进入循环状态,保证app进程的一直运行状态,looper相关内容在其他文章中有分析

通过attachApplication方法,会将当前进程的binder句柄传给AMS绑定管理起来,后续就可以通过AMS对当前应用进程进行操作管理,继续追踪就到AMS的方法调用

//ActivityManagerService.java
   public final void attachApplication(IApplicationThread thread, long startSeq) {
       synchronized (this) {
           attachApplicationLocked(thread, callingPid, callingUid, startSeq);
      }
  }

//主要分析主要的两个的步骤
   private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
           int pid, int callingUid, long startSeq) {
     //创建应用进程的application对象
      thread.bindApplication();
     //调用ATMS的启动页面的方法
     // See if the top visible activity is waiting to run in this process...
       if (normalMode) {
           try {
         didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
          } 
      }
  }

这个流程会去创建我们应用开发中常见的application对象,然后会去执行相应的activity启动显示页面的流程

Application的创建流程
//ActivityThread.java
public final void bindApplication(){
  AppBindData data = new AppBindData();
  sendMessage(H.BIND_APPLICATION, data);
}

public void handleMessage(Message msg) {
  switch (msg.what) {
    case BIND_APPLICATION:
          AppBindData data = (AppBindData)msg.obj;
          handleBindApplication(data);
          break;
  }
}

private void handleBindApplication(AppBindData data) {
   //会去获取一个LoadApk对象
   data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
   //创建应用的上下文ContextImpl
   final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);

Application app;
         try {
           //step_1
           app = data.info.makeApplication(data.restrictedBackupMode, null);
           mInitialApplication = app;
           try {
               mInstrumentation.onCreate(data.instrumentationArgs);//空实现
          }
           try {
           //step_2
               mInstrumentation.callApplicationOnCreate(app);
          } 
      }
}

public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
           CompatibilityInfo compatInfo) {
    return getPackageInfo(ai, compatInfo, null, false, true, false);
}

private LoadedApk getPackageInfo() {
 synchronized (mResourcesManager) {
   WeakReference<LoadedApk> ref;
   LoadedApk packageInfo = ref != null ? ref.get() : null;
   packageInfo =new LoadedApk();
   mPackages.put(aInfo.packageName,new WeakReference<LoadedApk>(packageInfo));
   return packageInfo;
}
}

由于入口函数中已经初始化了主线程的Looper循环机制,后续的事件通信也是走了handler的方式发送了一个

H.BIND_APPLICATION的消息,在接收到这个message后就会进入application的实际创建流程,首先会去实例化一个LoadApk对象并且初始化上下文

  • Step_1:实例化Application对象

这部分主要是一些参数的获取和赋值,以供实例化application对象使用

//LoadApk.java
public Application makeApplication(boolean forceDefaultAppClass,
           Instrumentation instrumentation) {
   Application app = null;
   String appClass = mApplicationInfo.className;
   if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }
   try {
        final java.lang.ClassLoader cl = getClassLoader();
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        //继续去实例化Application对象
        app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
  }

   return app;
}

//Instrumentation.java
   public Application newApplication(ClassLoader cl, String className, Context context)
           throws InstantiationException, IllegalAccessException, 
           ClassNotFoundException {
       //通过反射去实例化对象,然后调用其attach方法
       Application app = getFactory(context.getPackageName())
              .instantiateApplication(cl, className);
       app.attach(context);
       return app;
  }

   private AppComponentFactory getFactory(String pkg) {
       LoadedApk apk = mThread.peekPackageInfo(pkg, true);
       if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
       return apk.getAppFactory();
  }

//AppComponentFactory.java
   public @NonNull Application instantiateApplication(@NonNull ClassLoader cl,
           @NonNull String className)
           throws InstantiationException, IllegalAccessException, ClassNotFoundException {
       return (Application) cl.loadClass(className).newInstance();
  }

通过以上步骤,就反射实例化了应用进程的application对象,接下来进入第二步

  • Step_2 : callApplicationOnCreate
//Instrumentation.java
public void callApplicationOnCreate(Application app) {
   app.onCreate();
}

这就到了应用开发中常见的需要在应用启动进行初始化操作的Application中的Oncreat()回调!!终于看到了熟悉的方法调用了

涉及到一些相关的类还是比较多,通过流程图梳理一下

应用Application的创建流程.jpg

以上流程,在应用进程启动的入口的函数,实例化了application对象,并且触发了其OnCreate回调,接下来就进入了第二步,调用ATMS的attachApplication()方法

Activity的启动

回到前面的AMS的流程,在初始化的时候,会进入mAtmInternal.attachApplication的流程

//ActivityTaskManagerService.java
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
           synchronized (mGlobalLockWithoutBoost) {
    return mRootWindowContainer.attachApplication(wpc);         
  }

//WindowContainer.java
boolean attachApplication(WindowProcessController app) throws RemoteException {
       boolean didSomething = false;
final PooledFunction c = PooledLambda.obtainFunction(
RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
                           PooledLambda.__(ActivityRecord.class), app,
                           rootTask.topRunningActivity());
}

private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
           WindowProcessController app, ActivityRecord top) {
         try {
           if (mStackSupervisor.realStartActivityLocked(r, app,
                   top == r && r.isFocusable() /*andResume*/, true /*checkConfig*/)) {
               mTmpBoolean = true;
          }
        }
}

到这里结合上一篇文章中,在launcher进程启动的时候,也会执行到ActivityStackSupervisor.java中的startSpecificActivity()方法,然后在判断进程没有启动的时候,去孵化进程,在进程启动的时候,就会执行realStartActivityLocked()方法

//ActivityStackSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
       // Is this activity's application already running?
       final WindowProcessController wpc =
               mService.getProcessController(r.processName, r.info.applicationInfo.uid);

       if (wpc != null && wpc.hasThread()) {
           try {
               //在进程存在的时候,就会执行这个方法,所以这个方法就是Activity启动的入口
               realStartActivityLocked(r, wpc, andResume, checkConfig);
               return;
          } catch (RemoteException e) {}

      }

       final boolean isTop = andResume && r.isTopRunningActivity();
//上一篇分析了进程不存在的情况下,走这个孵化进程的流程
       mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
  }
Activity的创建启动

直接走源码流程

//ActivityStackSupervisor.java
   final ActivityTaskManagerService mService;

   boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
           boolean andResume, boolean checkConfig) throws RemoteException {
     // Create activity launch transaction.
     final ClientTransaction clientTransaction = ClientTransaction.obtain(
           proc.getThread(), r.appToken);
     mService.getLifecycleManager().scheduleTransaction(clientTransaction);
  }

//Atms中
   ClientLifecycleManager getLifecycleManager() {
       return mLifecycleManager;
  }

//ClientLifecycleManager.java
class ClientLifecycleManager {
     void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
       final IApplicationThread client = transaction.getClient();
       //方法参数的ClientTransaction类型
       transaction.schedule();
}

//ClientTransaction.java
public class ClientTransaction implements Parcelable, ObjectPoolItem {
     //这个是应用进程的句柄,在ActivityThread的main方法中有提到过
     //mgr.attachApplication(mAppThread, startSeq)
     //应用进程和AMS绑定的地方
private IApplicationThread mClient;
     public void schedule() throws RemoteException {
       mClient.scheduleTransaction(this);
  }
}

//ActivityThread.java
//.Stub就是binder通信的服务端执行具体逻辑的对象
private class ApplicationThread extends IApplicationThread.Stub {
         @Override
  public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
           //执行到父类的scheduleTransaction方法
           ActivityThread.this.scheduleTransaction(transaction);
      }
}

//ActivityThread中没有复写scheduleTransaction,会执行到父类的方法
//public final class ActivityThread extends ClientTransactionHandler
//ClientTransactionHandler.java
public abstract class ClientTransactionHandler {
     void scheduleTransaction(ClientTransaction transaction) {
       transaction.preExecute(this);
       //发送消息
       sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
  }
}

//ActivityThread.java
public final class ActivityThread extends ClientTransactionHandler {
  private final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);

  class H extends Handler {
       public void handleMessage(Message msg) {
         switch (msg.what) {
          case EXECUTE_TRANSACTION:
               //贯穿整个Android应用的handler通信机制
               final ClientTransaction transaction = (ClientTransaction) msg.obj;
               //接下来的执行逻辑
               mTransactionExecutor.execute(transaction);
               if (isSystem()) {}
               break;
        }
      }
    }
}

//TransactionExecutor.java
public class TransactionExecutor {
 public void execute(ClientTransaction transaction) {
   //继续调用
   executeCallbacks(transaction);
}

public void executeCallbacks(ClientTransaction transaction) {
    final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
    final int size = callbacks.size();
    for (int i = 0; i < size; ++i) {
      //ClientTransactionItem是一个抽象类
      final ClientTransactionItem item = callbacks.get(i);
      //执行到LauncherActivityItem
      item.execute(mTransactionHandler, token, mPendingActions);
    }
}
}

//LaunchActivityItem.java
public class LaunchActivityItem extends ClientTransactionItem {
     @Override
   public void execute(ClientTransactionHandler client, IBinder token,
           PendingTransactionActions pendingActions) {
       //将一些列的参数封装成ActivityClientRecord对象用于启动后续获取参数
       ActivityClientRecord r = new ActivityClientRecord(/*省略了参数*/);
       client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
  }
}

//ActivityTread重写了ClientTransactionHandler中的handleLaunchActivity方法
public Activity handleLaunchActivity(ActivityClientRecord r,
       PendingTransactionActions pendingActions, Intent customIntent) {
   //这里就看到了Activity的对象引用,接下来就是看具体的实例化过程
final Activity a = performLaunchActivity(r, customIntent);
   return a;
}

内容有点多,先将这部分内容整理一下

  • realStartActivityLocked执行后会去ATMS中通过一些列方法调用给主线程发送一个Handler消息EXECUTE_TRANSACTION

  • 在主线程的handler处理消息,并将事物分发给处理对象,最终回调到ActivityTread中的handleLaunchActivity方法

  • 在handleLaunchActivity中会返回一个Activity的对象,并通过执行performLaunchActivity去执行具体的Activity的实例化过程

有过Activity启动流程了解的朋友,看到performLaunchActivity方法就已经非常熟悉了,接下来继续追踪

//ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
ComponentName component = r.intent.getComponent();
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
    try {
      //通过反射实例化Activity对象
      java.lang.ClassLoader cl = appContext.getClassLoader();
      activity = mInstrumentation.newActivity(
              cl, component.getClassName(), r.intent);
      }

   if (activity != null) {
        //当实例化Activity对象后,继续执行callActivityOnCreate
       if (r.isPersistable()) {
          mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
          } else {
          mInstrumentation.callActivityOnCreate(activity, r.state);
      }
  }
}

//Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle) {
     prePerformCreate(activity);
     //继续往后执行
     activity.performCreate(icicle);
     postPerformCreate(activity);
}

//Activity.java
final void performCreate(Bundle icicle) {
     performCreate(icicle, null);
}

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
   if (persistentState != null) {
       onCreate(icicle, persistentState);
    } else {
       onCreate(icicle);
    }
}

到了这一步,看到了让人无比熟悉的的Activity的onCreate()方法,整个Activity的创建的流程的源码分析就先到这里,涉及的类很多,为了尽量保持单一职责,拆分出了很多类去进行管理,可以看出跟Activity密切相关的有AMS,PKMS,WMS,ATMS,Instrumentation等

后续会继续去追踪framework层的源码,将跟应用开发最常见使用的Activity的相关内容进一步分析

附上Acitvity创建流程的流程图


Activity的oncreat流程.jpg
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容