Skip to content

Activity

应用启动

新进程创建前

当用户点击一个应用图标,或者系统请求某个组件(泛指Activity,Service等)时,将是应用启动、Activity启动的一般时机。

  1. 构造Intent通过PackageManager来解析,其内部是用resolveIntent,若解析成功,则会保存解析结果到此Intent实例以避免后面再次解析。
  2. 检查权限,grantUriPermissionLocked。对于需要申请权限的Intent,需要确定目标组件拥有合适的权限。
  3. 接下来,由ActivityManagerService检查Intentflags比如FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_CLEAR_TOP来确定是否需要开启新的任务栈。
  4. 接下来检查,对于所需要的进程其ProcessRecord是否已经存在,若没有则需要为此组件创建进程。否则只需要进行任务栈的维护,不需要创建进程。

新进程创建

ActivityManagerService通过startProcessLocked方法,给Zygote进程以Socket通信发送启动参数。Zygote进程使用fork系统调用分离出子进程并且调用ZygoteInit.main()主方法。并实例化ActivityThread,返回进程id结果。

// ProcessList.java,注意这个entryPoint很重要,我找了半天,现在没有显式引用ActivityThread,而是指定className去反射找main方法
    final String entryPoint = "android.app.ActivityThread"; 

    return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
            runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
            instructionSet, invokeWith, startTime); 

新的应用进程进入ActivityThread.main,初始化了Java侧的handler即H类实例,Looper便开始loop,它所对应的线程即为UI线程、主线程。由此后续的通信,便可以基于此Looper和java侧的Hhandler实例。ActivityThread的内部类ApplicationThread实现了IApplicationThread这是AMS服务用于调用应用进程进行通信的一组接口,其中包括bindApplicationscheduleTransaction

// ActivityThread.java 已精简
 public static void main(String[] args) {
        AndroidOs.install();
        Environment.initForCurrentUser();
        TrustedCertificateStore.setDefaultUserDirectory(configDir);
        initializeMainlineModules();

        // Looper准备,绑定线程内Looper单例
        Looper.prepareMainLooper(); 

        // 创建ActivityThread实例,因为我们目前只是在main静态入口方法里。
        ActivityThread thread = new ActivityThread();

        // 在这里会用`ActivityManagerService`的`attachApplication`把`IApplicationThread`的实现实例`appThread`传递过去。由此AMS可以通过`IApplicationThread`和应用进程进行回调。比如后面的`ApplicationThread.bindApplication`
        thread.attach(false, startSeq);
        if (sMainThreadHandler == null) {
            //构造Java侧handler,即`H`类实例
            sMainThreadHandler = thread.getHandler();
        }
        //进入epoll
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

Application创建

接下来会由AMS调用IApplicationThread.bindApplication,其内部用H实例发送消息BIND_APPLICATION到UI线程,进而到handleBindApplication处理。比较关注的过程就是makeApplicationApplication.onCreate

// ActivityThread.java # handleBindApplication 大幅精简
    final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
    mInstrumentation = new Instrumentation();
    mInstrumentation.basicInit(this);
    Application app;
    app = data.info.makeApplication(data.restrictedBackupMode, null);
    if (!data.restrictedBackupMode) {
        if (!ArrayUtils.isEmpty(data.providers)) {
            installContentProviders(app, data.providers);
        }
    }
    mInstrumentation.onCreate(data.instrumentationArgs);
    mInstrumentation.callApplicationOnCreate(app);
主要的点不言自明。由此可以注意的是:

  • 无论是什么组件,但凡需要创建新的进程时,均会经历此初始化,即application的创建。
  • ContentProvider的创建时早于Application#onCreate的,而其他组件则不是。

Activity启动

当启动Activity的时候,会由AMS调用IApplicationThreadscheduleTransaction,进而由ApplicationThreadH发送一个EXECUTE_TRANSACTION信息,进而交给TransactionExecutor去处理事务,进而会分发给不同的LifecycleItem来处理事务。

// H
case EXECUTE_TRANSACTION:
    final ClientTransaction transaction = (ClientTransaction) msg.obj;
    mTransactionExecutor.execute(transaction);
    break;
进而
// TransactionExecutor.java 已精简
public void executeCallbacks(ClientTransaction transaction) {
    final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
    final IBinder token = transaction.getActivityToken();
    ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
    final int size = callbacks.size();
    for (int i = 0; i < size; ++i) {
        final ClientTransactionItem item = callbacks.get(i);
        item.execute(mTransactionHandler, token, mPendingActions);
        item.postExecute(mTransactionHandler, token, mPendingActions);
    }
}
也就是说,ClientTransactionItem是由服务端传入的。它的继承关系包含: ClientTransactionItem 子类

  • ActivityTransactionItem
    • ActivityConfigurationChangeItem
    • ActivityLifecycleItem
      • DestroyActivityItem
      • PauseActivityItem
      • ResumeActivityItem
      • StartActivityItem
      • StopActivityItem
    • ActivityRelaunchItem
    • ActivityResultItem
    • NewIntentItem
    • LaunchActivityItem

每个item的execute方法是其具体实现。对于Activity来说,先被Launch

// 大幅精简
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
        if (ThreadedRenderer.sRendererEnabled
                && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
            HardwareRenderer.preload();
        }
        WindowManagerGlobal.initialize();
        final Activity a = performLaunchActivity(r, customIntent);
        return a;
    }
// 核心内容,大幅精简
    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        java.lang.ClassLoader cl = appContext.getClassLoader();
        // 构造Activity
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);

        // attachBaseContext, 创建PhoneWindow。
        activity.attach(appContext, this, getInstrumentation(), r.token,
                r.ident, app, r.intent, r.activityInfo, title, r.parent,
                r.embeddedID, r.lastNonConfigurationInstances, config,
                r.referrer, r.voiceInteractor, window, r.configCallback,
                r.assistToken, r.shareableActivityToken);

        // 进入onCreate
        mInstrumentation.callActivityOnCreate(activity, r.state);
        return activity;
    }

到这里Activity的构造、启动就完成了。

总结

  • 应用启动首先需要解析Intent,确认启动方式、权限、是否能找到对应包、以及目标所需要的任务栈是否满足。再根据需要决定是否创建进程。
  • 创建进程由系统服务和Zygote进程通过socket通信,会发送大量的新进程启动参数。新进程启动后,会初始化系统服务、以及虚拟机的一些配置等。进而进入指定的入口类。一般是ActivityThread
  • ActivityThread内部有很多类。其中ApplicationThread实现了服务端对客户端的一些调用请求,主要方法包括bindApplicationscheduleTransaction。此外,ActivityThread的主方法会准备Looper并进入循环。任意线程均可以使用ActivityThread.getHandler()H实例来发送信息、回调给UI线程。
  • ActivityThread负责了不止一个activity的生命周期,而是所有此进程的activity。application的生命周期也是由它来负责。先由AMS对ApplicationThread发起bindApplication,之后它还会构造ClientTransactionItem并通过ApplicationThread发起scheduleTransaction进而周转Activity的生命周期。

关于Looper, Handler, Binder, 以及渲染流程,请参见“Android”section其他文章。

Activity启动模式

  1. standrad

    • 总是创建新的实例在当前的ActivityTask的栈上。
    • taskAffinity没作用。因为总是在当前的ActivityTask上。
    • 相当于在不同的ActivityTask上可以创建多个实例。
  2. singleTop

    • 如果当前已经是同一个实例,则不再创建新实例,而是onNewIntent。其他情况同前者。
  3. singleTask

    • 带有clearTop效果。当之前打开过此实例,后面在此task上插入了新的其他页面,又打开此页面时,会复用上次的,并清除所有之间的页面。
    • 如果指定了taskAffinity,与当前的task不符合,则会在新的appTask中的栈上打开。
  4. singleInstance

    • 与singleTask相似,但只允许自己出现在这个ActivityTask中。即使此时如果打开一个taskAffinity一样的但模式也是singleInstance的新页面时,这个task仍然只会保留新的页面,此时点击返回会退出。
    • 实际上此时打开任何Activity都会离开此Task,在新的task中打开。包括上面的情况。

activity生命周期细节

从activity A 打开 activity B,activity A的stop一定是在activity B的resume之后。至于为什么,可以思考下动画,动动脑子就能想得通。

onStop

此外,对于启动半透明/不透明的Activity来说,即android:windowIsTranslucent标志位差异,它的生命周期回调有所不同。如下图所示,即对于半透明的情况,Activity A不会触发onStop。

拓展阅读