您当前的位置:首页 > 电脑百科 > 程序开发 > 移动端 > Android

Android 操作系统之 Activity 的启动过程

时间:2022-08-08 16:54:41  来源:  作者:愿天堂没有代码

前言

上篇文章写到 Service 的启动过程; 相对来说Activity的启动过程比Service的启动过程更为复杂,其一Activity的生命周期方法比Service多,其二Activity具有启动模式和返回栈; 写本文的目的在于更清晰的梳理Activity的启动过程,加强自己的内功修炼,博客粉丝日益增多,力在以最简单的方式让大家理解,跟大家一起学习

一、Binder的基本理解

Activity的启动有多次IPC过程,所以Binder属于预备知识,帮助我们更好理解系统的C/S的这种架构模式

二、Activity启动的双向IPC过程

一般Android各个应用进程的启动都以这样一条路线,init进程 –> Zygote进程 –> SystemServer进程 –>各种应用进程

  • Init进程:linux的根进程,Android系统是基于Linux系统的,因此可以算作是整个android操作系统的第一个进程;
  • Zygote进程是所有应用进程的父进程,所有的应用进程都是它孵化出来的;
  • SystemServer进程含有一些核心的服务,比如ActivityManagerService,PackageManagerService,WindowManagerService等;
  • 各种应用进程:启动自己编写的客户端应用时,有自己的虚拟机与运行环境。

由此可知应用的第一个Activity的启动是多个进程相互配合的结果,多个进程相互配合就少不了使用Binder进行IPC了,现在看一次IPC调用的过程是怎样的。

 

上图大概说明了一次IPC的过程,或许你现在对里面各个类还不是很清楚,没关系,大致了解一下

ActivityManagerService (下文简称AMS),AMS是Android中最核心的服务,实现了ActivityManager,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,AMS提供了一个ArrayList mHistory来管理所有的Activity,Activity在AMS中的形式是ActivityRecord,Task在AMS中的形式为TaskRecord,进程在AMS中的管理形式为ProcessRecord,它在Android中特别重要

ActivityManagerNative (下文简称AMN):由于AMS是系统核心服务在SystemServer进程里面,很多API不能直接开放供客户端使用,所以需要通过IPC的方式,具体是这样的,ActivityManager类内部调用AMN的getDefault函数得到一个ActivityManagerProxy对象,通过它可与AMS通信

ActivityManagerProxy (下文简称AMP):AMP是AMS在客户端进程的一个代理,通过AMP里面的方法请求AMS

Instrumentation: InstrumentAIon是一个工具类,一个大管家。当它被启用时,系统先创建它,再通过它来创建其他组件;另外,系统和组件之间的交互也将通过Instrumentation来传递,这样,Instrumentation就能监测系统和这些组件的交互情况了。在实际使用中,我们可以创建Instrumentation的派生类来进行相应的处理。Android中Junit的使用到了Intrstrumentation

OK,现在我们知道,Activity是如何向AMS发出startActivity这个请求了,这意味着Activity可以与AMS进行通信,但是AMS却不能与Activity通信,Binder是单向的,所以在Activity发出请求之后,AMS需要通知Activity发生状态改变,要做到这一点,自然就在AMS到Activity这个过程建立一个Binder,如下:

 

大致过程就是,SystemServer进程在收到请求后,再通过IPC向应用进程发送scheduleLaunchActivity请求,应用进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息,主线程在收到Message后,创建目标Activity,并回调Activity.onCreate()等方法

对上面的理解不是太明白,在看下面这张图,简单多了;AMS到Activity这个过程建立了一个Binder,Activity到AMS这个过程也建立了一个Binder,这就能相互通信了

 

上图就是Activity与AMS之间的双向Binder连接, (备注:这个就是理解Activity启动流程的指南针,不记住这个,复杂的启动流程会让你晕头转向);Activity用IActivityManager提供的API向AMS提出执行某个动作的请求(本例中是启动RemoteService),AMS通过IApplicationThread提供的API来控制Activity所在的应用程序,这些API包括schedulePauseActivity()、scheduleStopActivity()等

IActivityManager接口定义的API,启动四大组件的等多种请求都在里面

 

IApplicationThread接口定义的API,一看就比IActivityManager高逼格一点,IActivityManager好多方法是start开头,表示去AMS请求,IApplicationThread以schedule开头,表示对Activity进行调度

 

分析到这里,我们不知不觉间忽略了两个问题,那就是启动Activity至少需要两个前提

第一是,应用进程存在,第二AMS已经初始化完毕; 在调用startActivity方法时候,如果我们的应用进程不存在,Activity能启动吗,当然是不能的,比如点击桌面图标的时候,这个时候需要先创建进程。关于Zygote孵化应用进程,这个暂时不说,先看看AMS服务注册

三、AMS服务注册

先忽略 Activity调用ActivityManagerService启动应用,直接从SystemServer的main方法说起

 /**
    * The main entry point from zygote.
    */
   public static void main(String[] args) {
       new SystemServer().run();
   }

run方法中,调用了startBootstrapServices

 private void startBootstrapServices() {
      
       ......
       //启动AMS服务
       Installer installer = mSystemServiceManager.startService(Installer.class);

       //请注意这里参数是Lifecycle,因为AMS是在Lifecycle里面new出来的
       mactivityManagerService = mSystemServiceManager.startService(
               ActivityManagerService.Lifecycle.class).getService();
       mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
       mActivityManagerService.setInstaller(installer);

       mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

       mActivityManagerService.initPowerManagement();

        ......
       mActivityManagerService.setSystemProcess();
     ......
}
 public SystemService startService(String className) {
       final Class<SystemService> serviceClass;
       try {
           serviceClass = (Class<SystemService>)Class.forName(className);
       } catch (ClassNotFoundException ex) {
           Slog.i(TAG, "Starting " + className);
       }
       return startService(serviceClass);
   }

继续

public <T extends SystemService> T startService(Class<T> serviceClass) {
       try {
           final String name = serviceClass.getName();
           // 1、创建服务
           final T service;
           try {
               Constructor<T> constructor = serviceClass.getConstructor(Context.class);
             // 如果传进来的是ActivityManagerService.Lifecycle对象,那么ActivityManagerService就能被创建
               service = constructor.newInstance(mContext);
           } catch (InstantiationException ex) {
               throw new RuntimeException("Failed to create service " + name
                       + ": service could not be instantiated", ex);
           }
           // 2、注册服务
           mServices.add(service);

           // 3、启动服务
           try {
               service.onStart();
           } catch (RuntimeException ex) {
               throw new RuntimeException("Failed to start service " + name
                       + ": onStart threw an exception", ex);
           }
           return service;
       } finally {
           Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
       }
   }
ActivityManagerService.JAVA

  public static final class Lifecycle extends SystemService {
       private final ActivityManagerService mService;

       public Lifecycle(Context context) {
           super(context);
         //ActivityManagerService被new出来了
           mService = new ActivityManagerService(context);
       }

       @Override
       public void onStart() {
         //  启动
           mService.start();
       }

       public ActivityManagerService getService() {
           return mService;
       }
   }
 private void start() {
       Process.removeAllProcessGroups();
       mProcessCpuThread.start();

       mBatteryStatsService.publish(mContext);
       mAppOpsService.publish(mContext);
       Slog.d("AppOps", "AppOpsService published");
       LocalServices.addService(ActivityManagerInternal.class, new LocalService());
   }

回到 startBootstrapServices里面调用的
mActivityManagerService.setSystemProcess();

public void setSystemProcess() {
       try {
           ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
           ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
           ServiceManager.addService("meminfo", new MemBinder(this));
           ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
           ServiceManager.addService("dbinfo", new DbBinder(this));
           ......


      // 设置application info LoadedApkinfo 有关 framework-res.apk
       ApplicationInfo info = mContext.getPackageManager().getApplicationInfo( "android", STOCK_PM_FLAGS);
       mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
       
       //给SystemServer进程创建ProcessRecord,adj值,就是将SystemServer进程加入到AMS进程管理机制中,跟应用进程一致
       synchronized (this) {
           ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
           app.persistent = true;
           app.pid = MY_PID;
           app.maxAdj = ProcessList.SYSTEM_ADJ;
           app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
           synchronized (mPidsSelfLocked) {
               mPidsSelfLocked.put(app.pid, app);
           }
           updateLruProcessLocked(app, false, null);
           updateOomAdjLocked();
 }

ServiceManager这里面注册了很多的服务,可通过dumpsys <服务名>命令查看。比如查看CPU信息命令dumpsys cpuinfo,查看graphics信息命令dumpsys gfxinfo

在Android中所有的核心服务,并不是直接给上层使用,都先交给ServiceManager管理,上层使用的时候可以从ServiceManager获取,ServiceManager相当于一个路由作用。现在来看一张经典的图。其中注册服务,获取服务以及使用服务,每一次都是一个完整的Binder IPC过程,可见理解Binder是多么的重要啊。关于AMS启动得深入了解

 

  • 注册服务:首先AMS注册到ServiceManager。AMS所在进程(SystemServer)是客户端,ServiceManager是服务端
  • 获取服务:Client进程使用AMS前,须先向ServiceManager中获取AMS的代理类AMP。该过程。AMP所在进程(应用进程)是客户端,ServiceManager是服务端
  • 使用服务: app进程根据得到的代理类AMP,便可以直接与AMS所在进程交互。该过程,AMP所在进程(应用进程)是客户端,AMS所在进程(SystemServer)是服务端

 

最后我想说:

学习没有捷径可言,我们要注意记学习,不仅要记,还要写心得体会,文字笔记、画图、总结等,方式很多,但是一定要自己认真去做,不要太相信自己的记忆,只有反复记忆,加深理解才行

同时,对于程序员而言,不单单是死记硬背,我们有更好的方式去学习,比如写demo去验证。复习知识点时,要及时跟你做过的项目结合起来,这样在面试时就知道怎么聊了,由项目讲到知识点,由一个知识点串联到另一个知识点。复习到一定阶段,可以尝试着去把这些东西串联起来,由点及面,形成知识体系

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们

技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

Android 架构师之路还很漫长,与君共勉



Tags:Android   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Android Emulator黑屏怎么办 Android模拟器黑屏解决方法
Android Emulator黑屏问题困扰了非常多的玩家,Android Emulator作为一款安卓模拟器,可以让你在电脑上运行和浏览安卓应用程序,但是程序本身不是很稳定,很容易会出现黑屏,启动不了...【详细内容】
2024-03-04  Search: Android  点击:(37)  评论:(0)  加入收藏
Android 谷歌三件套:解锁谷歌生态!
大家是不是遇到这个情况?当我们需要下载一些国外的游戏或者软件的时候,需要在手机里面安装Google Play商店,然后通过Google Play商店下载国外软件!为了帮助大家使用上各种好用的...【详细内容】
2024-01-02  Search: Android  点击:(113)  评论:(0)  加入收藏
Android开发中常见的Hook技术有哪些?
Hook技术介绍Hook技术是一种在软件开发中常见的技术,它允许开发者在特定的事件发生时插入自定义的代码逻辑。常见的应用场景包括在函数调用前后执行特定的操作,或者在特定的事...【详细内容】
2023-12-25  Search: Android  点击:(86)  评论:(0)  加入收藏
在Android应用开发中使用NFC功能
NFC介绍NFC是指“近场通讯”(Near Field Communication),它是一种短距离无线通信技术,允许设备在非接触或极短距离内进行通信。NFC通常用于移动支付、门禁系统、智能标签和其他...【详细内容】
2023-12-22  Search: Android  点击:(102)  评论:(0)  加入收藏
关于Android图像Bitmap类,你要知道的一切
Bitmap介绍Bitmap是一种图像文件格式,它由像素阵列组成,每个像素都有自己的颜色信息。在计算机图形学中,Bitmap图像可以被描述为一个二维的矩阵,其中每个元素代表一个像素的颜色...【详细内容】
2023-12-19  Search: Android  点击:(99)  评论:(0)  加入收藏
Android开发中如何进行单元测试?
单元测试介绍单元测试是软件开发中的一种测试方法,用于验证代码中的最小可测试单元(通常是函数或方法)是否按预期工作。单元测试通常由开发人员编写,旨在隔离和测试代码的特定部...【详细内容】
2023-12-11  Search: Android  点击:(168)  评论:(0)  加入收藏
我的手机我做主,如何为Android手机应用换图标?
作为一名Android用户,你是否曾经为自己的手机桌面感到单调而乏味?虽然Android系统的桌面定制性已经非常强大,但有时候我们还是希望能够在细节上做出一些改变,尤其是对于那些每天...【详细内容】
2023-12-10  Search: Android  点击:(61)  评论:(0)  加入收藏
了解Android系统架构中的HAL硬件抽象层
在Android系统中,HAL的存在使得不同厂商的硬件可以统一被上层的应用程序调用,从而提高了系统的兼容性和可移植性。HAL还可以帮助开发者更方便地开发应用程序,因为他们不需要为...【详细内容】
2023-12-06  Search: Android  点击:(203)  评论:(0)  加入收藏
谷歌 CEO 皮查伊建议 Android 用户不要侧载应用,称非常危险
iOS和Android的一个显著差异是,Android支持用户从第三方渠道安装应用程序(即“侧载”)。然而,谷歌似乎并不希望用户这样做。最近,在与Epic Store的法律诉讼中,谷歌首席执行官桑达...【详细内容】
2023-11-20  Search: Android  点击:(167)  评论:(0)  加入收藏
Android数据对象序列化原理与应用
序列化与反序列化「序列化」是将对象转换为可以存储或传输的格式的过程。在计算机科学中,对象通常是指内存中的数据结构,如数组、列表、字典等。通过序列化,可以将这些对象转换...【详细内容】
2023-11-14  Search: Android  点击:(273)  评论:(0)  加入收藏
▌简易百科推荐
Android Emulator黑屏怎么办 Android模拟器黑屏解决方法
Android Emulator黑屏问题困扰了非常多的玩家,Android Emulator作为一款安卓模拟器,可以让你在电脑上运行和浏览安卓应用程序,但是程序本身不是很稳定,很容易会出现黑屏,启动不了...【详细内容】
2024-03-04  18183游戏网    Tags:Android Emulator   点击:(37)  评论:(0)  加入收藏
Android开发中常见的Hook技术有哪些?
Hook技术介绍Hook技术是一种在软件开发中常见的技术,它允许开发者在特定的事件发生时插入自定义的代码逻辑。常见的应用场景包括在函数调用前后执行特定的操作,或者在特定的事...【详细内容】
2023-12-25  沐雨花飞蝶  微信公众号  Tags:Android   点击:(86)  评论:(0)  加入收藏
在Android应用开发中使用NFC功能
NFC介绍NFC是指“近场通讯”(Near Field Communication),它是一种短距离无线通信技术,允许设备在非接触或极短距离内进行通信。NFC通常用于移动支付、门禁系统、智能标签和其他...【详细内容】
2023-12-22  沐雨花飞蝶  微信公众号  Tags:Android   点击:(102)  评论:(0)  加入收藏
关于Android图像Bitmap类,你要知道的一切
Bitmap介绍Bitmap是一种图像文件格式,它由像素阵列组成,每个像素都有自己的颜色信息。在计算机图形学中,Bitmap图像可以被描述为一个二维的矩阵,其中每个元素代表一个像素的颜色...【详细内容】
2023-12-19  沐雨花飞蝶  微信公众号  Tags:Android   点击:(99)  评论:(0)  加入收藏
Android开发中如何进行单元测试?
单元测试介绍单元测试是软件开发中的一种测试方法,用于验证代码中的最小可测试单元(通常是函数或方法)是否按预期工作。单元测试通常由开发人员编写,旨在隔离和测试代码的特定部...【详细内容】
2023-12-11  沐雨花飞蝶  微信公众号  Tags:Android   点击:(168)  评论:(0)  加入收藏
一篇聊聊Jetpack Room实现数据存储持久性
Room介绍Room 是 Android Jetpack 组件库中的一部分,它是用于在 Android 应用中进行本地数据库访问和管理的库。Room 提供了一个抽象层,使开发者能够更轻松地访问 SQLite 数据...【详细内容】
2023-12-08  沐雨花飞蝶  微信公众号  Tags:Jetpack   点击:(143)  评论:(0)  加入收藏
了解Android系统架构中的HAL硬件抽象层
在Android系统中,HAL的存在使得不同厂商的硬件可以统一被上层的应用程序调用,从而提高了系统的兼容性和可移植性。HAL还可以帮助开发者更方便地开发应用程序,因为他们不需要为...【详细内容】
2023-12-06  沐雨花飞蝶  微信公众号  Tags:Android   点击:(203)  评论:(0)  加入收藏
我们一起聊聊 IntentService 与 Service 的区别?
Service介绍Service组件是Android应用开发中的四大组件之一,用于在后台执行长时间运行的操作或处理远程请求。它可以在没有用户界面的情况下执行任务,并且可以与其他应用组件...【详细内容】
2023-12-06  沐雨花飞蝶  微信公众号  Tags:IntentService   点击:(171)  评论:(0)  加入收藏
Android数据对象序列化原理与应用
序列化与反序列化「序列化」是将对象转换为可以存储或传输的格式的过程。在计算机科学中,对象通常是指内存中的数据结构,如数组、列表、字典等。通过序列化,可以将这些对象转换...【详细内容】
2023-11-14  沐雨花飞蝶  微信公众号  Tags:Android   点击:(273)  评论:(0)  加入收藏
你了解Android中的SELinux吗?
SELinux介绍SELinux(Security-Enhanced Linux)是一种安全增强的Linux操作系统,它通过强制访问控制(MAC)机制来提供更高级别的系统安全保护。相比于传统的Linux访问控制机制(DAC),SEL...【详细内容】
2023-11-09  沐雨花飞蝶  微信公众号  Tags:Android   点击:(267)  评论:(0)  加入收藏
站内最新
站内热门
站内头条