安卓Activity的创建和启动流程源码分析

概述

安卓开发的程序猿都知道四大组件之一的Activity的重要性,但可能有很多人并不了解Activity的创建流程和声生命周期调用流程,只是在运用上行云流水。

那么希望这篇文章对那些还不够了解Activity的同志们来说能有所帮助。

注:以下源码基于Android11

Android入口函数

在Java程序里,项目的入口函数是main函数,这个想必大家也都知道,那么我们安卓项目又是怎么启动的呢?对,不要怀疑,在我们开发的安卓项目中,也是有一个入口main函数,安卓中这个main函数在源码ActivityThread.java类中:

//ActivityThread.java
public static void main(String[] args) {
   
    ...此处省略一万个字母
}

是不是很眼熟,跟Java中一样。当我们点击手机屏幕上的App图标开启应用的时候,Android首先调用的是这个main方法,ApplicationActivity就在这个main函数中创建。

源码分析

接下来我们就进入源码分析环节,直接看mian方法里面的源码:

//ActivityThread.java
public static void main(String[] args) {
   
    ...
    //为主线程创建Looper
     Looper.prepareMainLooper();
    long startSeq = 0;
    if (args != null) {
   
        for (int i = args.length - 1; i >= 0; --i) {
   
            if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
   
                startSeq = Long.parseLong(
                        args[i].substring(PROC_START_SEQ_IDENT.length()));
            }
        }
    }
    //1.创建ActivityThread
    ActivityThread thread = new ActivityThread();
    //2.将当前app与Android系统的AMS服务连接起来,记住此处attach方法的第一个参数
    thread.attach(false, startSeq);
    ...
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

上面注释1的部分创建了ActivityThread,然后在注释2的部分调用了attach方法,接下来我们点进thread.attach(false, startSeq)方法里面继续看:

//ActivityThread.java
private void attach(boolean system, long startSeq) {
   
    if (!system) {
   
        ...
        //1.获取AMS的本地代理对象IActivityManager
        final IActivityManager mgr = ActivityManager.getService();
        try {
   
            //2.绑定Application
            mgr.attachApplication(mAppThread, startSeq);
        } catch (RemoteException ex) {
   
            throw ex.rethrowFromSystemServer();
        }
        ...
    } else {
   
        ...
    }
}

在上面的attach方法里面,注释1的部分,通过AIDL,获取了AMS的本地代理对象IActivityManager,它是作为应用进程请求系统进程的接口,实现跟AMS服务跨进程通信(通过AIDL实现跨进程通信)。然后上面注释2的部分通过IActivityManager实例调用attachApplication方法,该方法主要是绑定Application,让AMS跟Application连接起来,从而让当前app跟Android系统实现绑定,方便系统管理当前app。接着进入mgr.attachApplication(mAppThread, startSeq)方法里面:

//ActivityManagerService.java
public final void attachApplication(IApplicationThread thread, long startSeq) {
   
    if (thread == null) {
   
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
   
        //1.获取pid(系统创建并分配)
        int callingPid = Binder.getCallingPid();
        //2.获取uid(系统创建并分配)
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        //3.连接Application
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        Binder.restoreCallingIdentity(origId);
    }
}

此处需要说明一下,attachApplicationActivityManagerService中的方法,ActivityManagerService继承了IActivityManagerStub内部类:

ActivityManagerService

当获取到pid和uid之后,紧接着将这两个值作为参数传入到attachApplicationLocked方法里面,来看看这个方法:

//ActivityManagerService.java
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
   
    //1.进程记录类
    ProcessRecord app;
    ...
    if (pid != MY_PID && pid >= 0) {
   
        synchronized (mPidsSelfLocked) {
   
            //2.通过pid获取进程记录类
            app = mPidsSelfLocked.get(pid);
        }
        ...
    }
    ...
    //通过ProcessRecord实例获取ActiveInstrumentation实例
    final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
    ...
    if (app.isolatedEntryPoint != null) {
   
        ...
    } else if (instr2 != null) {
   //当前进程是否处于活动状态
        //3.绑定到当前线程
        thread.bindApplication(processName, appInfo, providerList,
               instr2.mClass,
               profilerInfo, instr2.mArguments,
               instr2.mWatcher,
               instr2.mUiAutomationConnection, testMode,
               mBinderTransactionTrackingEnabled, enableTrackAllocation,
               isRestrictedBackupMode || !normalMode, app.isPersistent(),
               new Configuration(app.getWindowProcessController().getConfiguration()),
                                 app.compat, getCommonServicesLocked(app.isolated),
                                 mCoreSettingsObserver.getCoreSettingsLocked(),
                                 buildSerial, autofillOptions, contentCaptureOptions,
                                 app.mDisabledCompatChanges);
    } else {
   
        //4.绑定到当前线程
        thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
               null, null, null, testMode,
               mBinderTransactionTrackingEnabled, enableTrackAllocation,
               isRestrictedBackupMode || !normalMode, app.isPersistent(),
               new Configuration(app.getWindowProcessController().getConfiguration()),
                                 app.compat, getCommonServicesLocked(app.isolated),
                                 mCoreSettingsObserver.getCoreSettingsLocked(),
                                 buildSerial, autofillOptions, contentCaptureOptions,
                                 app.mDisabledCompatChanges);
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值