zoukankan      html  css  js  c++  java
  • Activity组件的启动过程

    Activity是Android应用程序的四大组件之一,负责管理Android应用程序界面。一个应用程序中的多个Activity可能运行在同一个进程中,也可能运行在不同的进程中。不同进程中的Activity组件通过Binder进程间通信机制来传输数据。

    从App程序的角度出发,Activity组件分为两类,一个是根Activity,一个是子Activity。根Activity以快捷图标的形式显示在应用程序的启动器中,它的启动过程就表示了一个App应用程序的启动过程。Activity的启动又分为“显示启动”、“隐式启动”。它们的启动过程都是类似的。唯一的区别在于系统是根据类名启动,还是根据组件名称来找到并启动。从软件工程的角度,隐式启动Activity的方式,可以减少Android应用程序组件间的依赖关系。

     

     

     当MainActivity组件被应用程序启动器中的Launcher组件启动起来之后,通过“adb shell dumpsys activity”命令可以查看到程序Activity相关启动信息:

     可以看到,所有的Activity都会进入到一个堆栈当中,后启动的Activity组件会位于前面启动的Activity组件上面。MainActivity组件是由Lanucher组件来启动的,而Lanucher组件又是通过Activity管理服务ActivityManagerService来启动MainActivity的(ActivityManagerService是一个系统关键服务,它运行在系统进程System中,负责启动和调度应用程序组件)。又因为MainActivity组件、Lanucher组件和ActivityManagerService是分别运行在不同的进程中,因此一个MainActivity组件的启动过程,就涉及到了三个进程。它们之间通过Binder进程间的通信机制来完成MainActivity的启动过程。

    Launcher组件启动一个MainActivity组件的过程如下:

    1. Launcher组件向ActivityManagerService发送一个启动MainActivity组件的进程间通信请求。
    2. ActivityManagerService首先将要启动的MainActivity组件的信息保存下来,然后再向Launcher组件发送一个进入中止状态的进程间通信请求。
    3. Launcher组件进入到中止状态之后,就会向ActivityManagerService发送一个已进入中止状态的进程间通信请求,以便ActivityManagerService可以继续执行启动MainActivity组件的操作。
    4. ActivityManagerService发现用来运行MainActivity组件的应用程序进程不存在,因此,就会先启动一个新的应用程序进程。
    5. 新的应用程序进程启动完成之后,就会向ActivityManagerService发送一个启动完成的进程间通信请求,以便ActivityManagerService可以继续执行启动MainActivity组件的操作。
    6. ActivityManagerService将第2步保存下来的MainActivity组件的信息发送给第4步创建的应用程序进程,以便它可以将MainActivity组件启动起来。

    (MainActivity的启动过程)从步骤1,到步骤5,如图所示:

     在系统源码package/apps/Launcher2/src/com/android/launcher2/Launcher.java类中有一个startActivitySafely方法:

     1 boolean startActivitySafely(View v, Intent intent, Object tag) {
     2         boolean success = false;
     3         try {
     4             success = startActivity(v, intent, tag);
     5         } catch (ActivityNotFoundException e) {
     6             Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
     7             Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
     8         }
     9         return success;
    10 }

    当我们在应用程序启动器Launcher的界面上点击一个应用程序的快捷图标时,Launcher组件的成员函数startActivitySafely就会被调用,来启动这个应用程序的根Activity,其中,要启动的根Activity的信息就包含在参数Intent当中。

    例如,当应用程序Activity的MainActivity组件被Launcher组件启动时,参数Intent所包含的Activity组件信息就如下所示:

    1 action = "android.intent.action.Main"
    2 category = "android.intent.category.LAUNCHER"
    3 cmp = "com.szcm.sample.huolongluo.ui.activity.main.MainActivity"

    第1行和第2行分别表示要启动的Activity组件的Action名称和Category名称。而第3行表示这个Activity组件是由“com.szcm.sample.huolongluo.ui.activity.main.MainActivity”类来实现的。

    这时候会思考,Launcher组件是如何获得这些信息的?系统在启动时,会启动一个Package管理服务PackageManagerService(简称PMS),并且通过它来安装系统中的应用程序。PMS在安装一个应用程序的过程中,会对它的清单文件AndroidManifest.xml进行解析,从而得到它里面的组件信息。系统启动完成之后,就会将Launcher组件启动起来。Launcher组件在启动过程中,会向PMS查询所有所有Action名称等于“Intent.ACTION_MAIN”,并且Category名称等于“Intent.CATEGORY_LAUNCHER”的Activity组件,最后为每一个Activity组件创建一个快捷图标,并且将它们的信息与各自的快捷图标关联起来,以便用户在点击它们的时候,可以将对应的根Activity组件启动起来。

  • 相关阅读:
    Git标签使用技巧
    Git入门基本概述
    过滤器+缓存在.NET5WebApi项目中的简单使用
    在.NET5中 使用JWT鉴权授权
    Git常用开发命令
    时间戳的实际使用
    两个日期字段相减,进行计算
    MQ的理论理解
    第一周学习C语言的总结!
    问题(the question)
  • 原文地址:https://www.cnblogs.com/huolongluo/p/15684716.html
Copyright © 2011-2022 走看看