Activity启动流程详解(基于api28)

本文详细分析了Android API28版本中Activity的启动流程,从普通Activity和根Activity的创建过程,到Activity请求AMS、AMS处理请求以及ActivityThread创建Activity的每个阶段。文中介绍了涉及的关键类如Instrumentation、ActivityThread、AMS及其交互,帮助开发者理解Android应用启动背后的机制。
摘要由CSDN通过智能技术生成

文章已在『技术最TOP』公众号发布

前言

Activity作为Android四大组件之一,他的启动绝对没有那么简单。这里涉及到了系统服务进程,启动过程细节很多,这里我只展示主体流程。activity的启动流程随着版本的更替,代码细节一直在进行更改,每次都会有很大的修改,如android5.0 android8.0。我这里的版本是基于android api28,也是目前我可以查得到的最新源码了。事实上大题的流程是相同的,掌握了一个版本,其他的版本通过源码也可以很快地掌握。

因为涉及到不同的进程之间的通信:系统服务进程和本地进程,在最新版本的android使用的是AIDL来跨进程通信。所以需要对AIDL有一定的了解,会帮助理解整个启动流程。

源码部分的讲解涉及到很多的代码讲解,可能会有一点不适,但还是建议看完源码。源码的关键代码处我都会加上注释,方便理解。

代码不会过分关注细节,只注重整体流程。想知道具体细节可以去查看源码。每份代码所在的路径我都会在代码前面标注出来,各位可以去查看相对应的源码。

每部分源码前我都会放流程图,一定要配合流程图食用,不然可能会乱。

整体流程概述

这一部分侧重于对整个启动流程的概述,在心中有大体的概念,这样可以帮助对下面具体细节流程的理解。

普通Activity的创建

普通Activity创建也就是平常我们在代码中采用startActivity(Intent intent)方法来创建Activity的方式。总体流程如下图:

aYQwF0.png

启动过程设计到两个进程:本地进程和系统服务进程。本地进程也就是我们的应用所在进程,系统服务进程为所有应用共用的服务进程。整体思路是:

  1. activity向Instrumentation请求创建

  2. Instrumentation通过AMS在本地进程的IBinder接口,访问AMS,这里采用的跨进程技术是AIDL。

  3. 然后AMS进程一系列的工作,如判断该activity是否存在,启动模式是什么,有没有进行注册等等。

  4. 通过ClientLifeCycleManager,利用本地进程在系统服务进程的IBinder接口直接访问本地ActivityThread。

    ApplicationThread是ActivityThread的内部类,IApplicationThread是在远程服务端的Binder接口

  5. ApplicationThread接收到服务端的事务后,把事务直接转交给ActivityThread处理。

  6. ActivityThread通过Instrumentation利用类加载器进行创建实例,同时利用Instrumentation回调activity的生命中周期

这里涉及到了两个进程,本地进程主要负责创建activity以及回调生命周期,服务进程主要判断该activity是否合法,是否需要创建activity栈等等。进程之间就涉及到了进程通信:AIDL。(如果不熟悉可以先去了解一下,但可以简单理解为接口回调即可)

下面介绍几个关键类:

  • Instrumentation是activity与外界联系的类(不是activity本身的统称外界,相对activity而言),activity通过Instrumentation来请求创建,ActivityThread通过Instrumentation来创建activity和调用activity的生命周期。

  • ActivityThread,每个应用程序唯一一个实例,负责对Activity创建的管理,而ApplicationThread只是应用程序和服务端进程通信的类而已,只负责通信,把AMS的任务交给ActivityThread。

  • AMS,全称ActivityManagerService,负责统筹服务端对activity创建的流程。

    其他的类,后面的源码解析会详解。

根Activity的创建

根Activity也就是我们点击桌面图标的时候,应用程序第一个activity启动的流程。这里我侧重讲解多个进程之间的关系,下面的源码也不会讲细节,只讲解普通activity的创建流程。这里也相当于一个补充。先看整体流程图:

aYGZVJ.png

主要涉及四个进程:

  • Launcher进程,也就是桌面进程
  • 系统服务进程,AMS所在进程
  • Zygote进程,负责创建进程
  • 应用程序进程,也就是即将要启动的进程

主要流程:

  1. Launcher进程请求AMS创建activity
  2. AMS请求Zygote创建进程。
  3. Zygote通过fork自己来创建进程。并通知AMS创建完成。
  4. AMS通知应用进程创建根Activity。

和普通Activity的创建很像,主要多了创建进程这一步。

源码讲解

Activity请求AMS的过程
流程图
aGokDO.png
源码
  1. 系统通过调用Launcher的startActivitySafely方法来启动应用程序。Launcher是一个类,负责启动根Activity。

    这一步是根Activity启动才有的流程,普通启动是没有的,放在这里是作为一点补充而已

    packages/apps/Launcher3/src/com/android/launcher3/Launcher.java/;
    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
         
        	//这里调用了父类的方法,继续查看父类的方法实现
            boolean success = super.startActivitySafely(v, intent, item);
            ...
            return success;
        }
        
    
    packages/apps/Launcher3/src/com/android/launcher3/BaseDraggingActivity.java/;
    public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
         
            ...
            // Prepare intent
            //设置标志singleTask,意味着在新的栈打开
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            if (v != null) {
         
                intent.setSourceBounds(getViewBounds(v));
            }
            try {
         
                boolean isShortcut = Utilities.ATLEAST_MARSHMALLOW
                        && (item instanceof ShortcutInfo)
                        && (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
                        || item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
                        && !((ShortcutInfo) item).isPromise();
                //下面注释1和注释2都是直接采用startActivity进行启动。注释1会做一些设置
                //BaseDraggingActivity是继承自BaseActivity,而BaseActivity是继承自Activity
                //所以直接就跳转到了Activity的startActivity逻辑。
                if (isShortcut) {
         
                    // Shortcuts need some special checks due to legacy reasons.
                    startShortcutIntentSafely(intent, optsBundle, item);//1
                } else if (user == null || user.equals(Process.myUserHandle())) {
         
                    // Could be launching some bookkeeping activity
                    startActivity(intent, optsBundle);//2
                } else {
         
                    LauncherAppsCompat.getInstance(this).startActivityForProfile(
                            intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
                }
                
               ...
            } 
        	...
            return false;
        }
    
  2. Activity通过Instrumentation来启动Activity

    /frameworks/base/core/java/android/app/Activity.java/;
    public void startActivity(Intent intent, @Nullable Bundle options) {
         
        	//最终都会跳转到startActivityForResult这个方法
            if (options != null) {
         
                startActivityForResult(intent, -1, options);
            } else {
         
                // Note we want to go through this call for compatibility with
                // applications that may have overridden the method.
                startActivityForResult(intent, -1);
            }
        }
    
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
                @Nullable Bundle options) {
         
        	//mParent是指activityGroup,现在已经采用Fragment代替,这里会一直是null
        	//下一步会通过mInstrumentation.execStartActivity进行启动
            if (mParent == null) {
         
                options = transferSpringboardActivityOptions(options);
                Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);//1
                if (ar != null) {
         
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
                }
                ...
            }
        ...
    }
    
  3. Instrumentation请求AMS进行启动。该类的作用是监控应用程序和系统的交互。到此为止,任务就交给了AMS了,AMS进行一系列处理后,会通过本地的接口IActivityManager来进行回调启动activity。

    /frameworks/base/core/java/android/app/Instrumentation.java/;
    public ActivityResult execStartActivity(
                Context who, IBinder contextThread, IBinder token, Activity target,
                Intent intent, int requestCode, Bundle options) {
         
        ...
        //这个地方比较复杂,先说结论。下面再进行解释    
        //ActivityManager.getService()获取到的对象是ActivityManagerService,简称AMS
        //通过AMS来启动activity。AMS是全局唯一的,所有的活动启动都要经过他的验证,运行在独立的进程中
        //所以这里是采用AIDL的方式进行跨进程通信,获取到的对象其实是一个IBinder接口
            
        //注释2是进行检查启动结果,如果异常则抛出,如没有注册。
        try {
         
                intent.migrateExtraStreamToClipData();
                intent.prepareToLeaveProcess(who);
                int result = ActivityManager.getService()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);//1
                checkStartActivityResult(result, intent);//2
            } catch (RemoteException e) {
         
                throw new RuntimeException("Failure from system", e);
            }
            return null;
        
    }
    

    这一步是通过AIDL技术进行跨进行通信。拿到AMS的代理对象,把启动任务交给了AMS。

    /frameworks/base/core/java/android/app/ActivityManager.java/;
    //单例类
    public static IActivityManager getService() {
          
    return IActivityManagerSingleton.get();
    }
    
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
    new Singleton<IActivityManager>() {
          
    @Override
    protected IActivityManager create() {
          
    //得到AMS的IBinder接口
    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
    //转化成IActivityManager对象。远程服务实现了这个接口,所以可以直接调用这个
    //AMS代理对象的接口方法来请求AMS。这里采用的技术是AIDL
    final IActivityManager am = IActivityManager.Stub.
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值