Android进阶知识树——Android四大组件启动过程

2023-10-30

Android的四大钻无论对开发者或是用户都意义重大,对于用户来说应用就是Activity,用户所能看到的和交互的都发生在Activity中,对于开发者来说四大组件更是开发功能个展示功能的基础和媒介,对于初级开发者每天的工作都在和四大组件打交道,它也成为初级开发者成长的重要一关,本文就从过年源码的角度分析下四大组件的启动过程;

1、Activity启动过程

Activity是我们打交道最多的组件,也是初学者接触最早的组件,特的使用范围和频率也最多,使用如此频繁的Activity你究竟了解多少呢?下面从源码的角度一起分析一下Activity的启动过程,在分析源码之前先介绍两个系统服务接口IActivityManager和IApplicationThread,它们都是在服务端只用Binder通信,(关于BinderAndroid进阶知识树——Android 多进程、Binder 你必须知道的一切)具体在本地的两个代理类如下:

  • IApplicationThread
class ApplicationThread extends IApplicationThread.Stub{
   ...}
  • IActivityManager
class ActivityManagerService extends IActivityManager.Stub{
   ……}

由上面的两个代理类知道,系统中使用AIDL实现客户端和服务端的通信,介绍这两个代理类后,这里先介绍下程序在IActivityManager中如何与IApplicationThread交互的,开发者都知道Android程序的开始会执行ActivityThread.main()方法,在main()中创建了ApplicationThread实例并完成了在Ams中的设置

final ApplicationThread mAppThread = new ApplicationThread(); // 实例化ApplicaitonThread

ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);//main()中调用attach()

 private void attach(boolean system, long startSeq) {
   
     final IActivityManager mgr = ActivityManager.getService(); 
     mgr.attachApplication(mAppThread, startSeq);
 }

在main()方法中调用了attach(),attach()中通过ActivityManager.getService()获取IActivityManager接口的代理类AMS,然后调用AMS.attachApplication()传入mAppThread对象;

  @Override
    public final void attachApplication(IApplicationThread thread, long startSeq) {
   
        synchronized (this) {
   
            int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);
        }
    }

在attachApplication中调用attachApplicationLocked()传入thread对象,attachApplicationLocked中调用了ProcessRecord.makeActive()在内部保存thread,这样AMS中就持有了ApplicationThread中代理的Binder对象;

  app.makeActive(thread, mProcessStats); //
  
    public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
   
            thread = _thread;
    }

上面实现了AMS和ApplicationThread的通信,那下面开始进入Activity的启动过程分析;

  • 执行启动Activity
startActivity()

Activity的启动是从一句startActivity()开始的,无论是否使用RequestCode启动,启动过程最终都会调用Activity的startActivityForResult()

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
   
        if (mParent == null) {
   
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
          }
  }

startActivityForResult()中调用会调用Instrumentation.execStartActivity(),Instrumentation在程序的启动和Activity的启动中起着重要的作用,而且在插件化中通过Hook系统中的Instrumentation对象还可以实现更多的功能,本篇指分析和Activity启动相关的

  • execStartActivity()
int result = ActivityManager.getService() //1
    .startActivity(whoThread, who.getBasePackageName(), intent,
            intent.resolveTypeIfNeeded(who.getContentResolver()),
            token, target != null ? target.mEmbeddedID : null,
            requestCode, 0, null, options);
checkStartActivityResult(result, intent);  //2、检查Activity的启动结果
  1. 注释1处调用IActivityManager代理类,IActivityManager是系统的服务接口,在此处采用Binder通信,ActivityManager.getService() 获取到的是它代理实现类ActivityManagerService,然后调用ActivityManagerService.startActivity()方法启动活动
  2. 在AMS启动活动后,调用checkStartActivityResult()检查启动结果,会根据具体的失败原因抛出异常
  • ActivityManager.getService():获取IActivityManager的代理类
public static IActivityManager getService() {
   
    return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
   
            @Override
            protected IActivityManager create() {
   
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };

此处参照Android 8.1 源码,在系统中IActivityManager使用Singleton封装单例提供,在getService()中通过IActivityManagerSingleton.get()获取,get()会调用Singleton的create()通过ServiceManager获取对应的Binder,在根据Binder获取代理对象即ActivityManagerService对象,到此程序进入AMS中

  • AMS中的startActivity()中经过一系列的调用代码最终执行到ActivityStackSupervisor的realStartActivityLocked(),realStartActivityLocked中调用IApplication接口方法处理LaunchActivity
  app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        System.identityHashCode(r), r.info,
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, !andResume,
                        mService.isNextTransitionForward(), profilerInfo);

此处IApplication接口的代理类为ApplicationThread,也就是方法最终进入ApplicationThread类中,ApplicationThread为ActivityThread中的内部类,它通过Handler发送消息方式与ActivityThread通信;

 @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
   
            ActivityClientRecord r = new ActivityClientRecord();
          .......
            r.overrideConfig = overrideConfig;
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

ApplicationThread中创建ActivityClientRecord对象保存活动信息,然后发送Handler消息,handler消息最终被ActivityThread中的Handler子类H所消耗,在H的handleMessage()中最终调用ActivityThread中startActivityNow()方法;

  • ActivityThread的startActivityNow()来启动Activity
public final Activity startActivityNow(){
   
ActivityClientRecord record = new ActivityClientRecord()// 1
r.token = token;
r.ident = 0;
r.intent = intent;
r.state = state;
r.parent = parent;
r.embeddedID = id;
r.activityInfo = activityInfo;
r.lastNonConfigurationInstances = lastNonConfigurationInstances;
return performLaunchActivity(r, null);//2
}

在startActivityNow()中,首先创建ActivityClientRecord保存activity启动信息,然后直接调用performLaunchActivity()启动活动,performLaunchActivity方法至关重要,Activity的一系列的初始化都在其中完成;

1.1、performLaunchActivity()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
   
ContextImpl appContext = createBaseContextForActivity(r);   //1、
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); //2、调用Instrumentation实例的方法
 ContextImpl appContext = createBaseContextForActivity(r); //3、创建Activity的Context对象
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);
//5
if (r.isPersistable()) {
   
    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
   
    mInstrumentation.callActivityOnCreate(activity, r.state);
}
r.setState(ON_CREATE)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android进阶知识树——Android四大组件启动过程 的相关文章

  • 如何以轻松的方式实现身份验证?

    我正在使用 python 在网络应用程序谷歌应用程序引擎上构建图片日记 用户可以注册并将照片发布到他们的日记中 另外 我正在尝试尽可能地遵循 REST 架构 Web 应用程序的身份验证方案基于以下形式 1 从前端发布用户名 密码2 认证成功
  • Powershell:捕获无法启动服务时引发的异常

    我似乎无法捕获抛出的异常Start Service 这是我的代码 try start service SomeUnStartableService catch Microsoft PowerShell Commands ServiceCom
  • 检测服务中的屏幕方向变化[重复]

    这个问题在这里已经有答案了 一个非常简单直接的问题 服务是否可以检测屏幕方向的变化 如果是这样 怎么办 此链接将回答您的问题 如何使用服务来监控 Android 中的方向变化 https stackoverflow com question
  • 如何在偏好更改时重新安排警报管理器

    我有一个 Android 服务 当手机启动时 广播接收器会收到通知 并安排服务以 X 分钟的间隔重复运行 从此以后 每隔 X 分钟 另一个广播接收器就会收到这些通知并启动该服务 该服务完成其工作并退出 到目前为止 一切都很好 现在我希望这
  • phpstorm symfony2 缺少服务警告

    我已经为 Phpstorm 安装了 Symfony2 插件 但我无法让 IDE 查看这些现有服务或其他注入的对象 能否以某种方式修复这些问题 从而使警告消失 我遇到了类似的问题 建议仔细检查以下内容 正如 Marcel建议的 检查你的Sym
  • 从另一个控制器调用 WebApi 控制器

    所以我的解决方案中有两个项目 两者都是WebApi 我在两者中都有控制器 我可以从客户端调用它们 javascript 问题是我需要从第一个项目的控制器中的方法调用第二个项目的控制器中的方法 我还认为我应该声明我需要调用的方法是 Post
  • 4 层(对于 N 层)架构示例?

    最近 我的一个朋友向我询问 N 层架构 我能够通过示例向他解释 1 2 和 3 层架构 但当我想给出超过 3 层的例子时 我就陷入了困境 我用谷歌搜索并大量寻求帮助 但找不到任何像样的例子 事实上 它被命名为 N 层 这让我认为 N 可以是
  • 如何从广播接收器中取消注册侦听器并停止服务

    在我的应用程序中 我有一个广播接收器 当接收到短信中的关键字时 它会启动一项跟踪手机 GPS 位置的服务 我这样做使用 context startService new Intent context TrackGPS class 我还需要能
  • Angular 服务测试出了什么问题?

    我有一个调用外部网络服务的服务 angular module myApp services service autoCmpltDataSvc function http var innerMatch function data return
  • Windows服务之间如何通信

    我有 2 个使用 C 创建的 Windows 服务 我希望其中一个服务调用第二个 Windows 服务中的函数 我该怎么做呢 EDIT 问题是我必须运行该应用程序 我不需要它们 相反服务进程也很好 但我need这2个应用程序进行通信 这2个
  • Android 语音识别服务在 <= Ice Cream Sandwich 上速度慢得多

    我有一个正在实现 RecognitionListener 的服务 如下所示 Android 语音识别作为 Android 4 1 和 4 2 上的服务 https stackoverflow com questions 14940657 a
  • 致命信号 11 (SIGSEGV),代码 1,故障地址 (RenderThread)

    当双击附加到窗口管理器的元素时 我试图停止服务 Override public boolean onTouch View v MotionEvent event switch event getAction case MotionEvent
  • 如何在 Android 中与正在运行的线程进行服务通信

    我的目标是推出一项能够满足所有应用程序网络需求的服务 我想也许打开2个套接字用于数据传输 我希望异步处理数据 所以我想我应该在两个单独的线程中运行它们 每个线程针对每个套接字 这样数据就可以在两个不同的 链接 异步中进行流式传输 所以 我希
  • 如何每天中午以及每次启动时运行服务

    在我的应用程序中 我有一个 SQLite 数据库 其中有一个表 其中包含以毫秒为单位的日期行 我希望每天显示一条通知IF自上次存储在我的数据库中的日期值以来已经过去了 30 天 服务似乎是完成此检查的好方法 我遇到了 Commonsware
  • 服务崩溃,事件名称为 [CLR20r3] [重复]

    这个问题在这里已经有答案了 我已经创建了一项服务 Net c 基本上定期发送电子邮件 该服务在我的上运行良好x32 XP机器但是当我部署时x64 build基于另一个 x64 Windows Server 2008 R2机器 服务启动并在几
  • Grails 在 Service 类中获取 Session 和 Management

    我对 Grails 会话有疑问 我正在考虑为我的会话处理提供一个服务类 所以我创建了一个名为 SessionService 的类 在 grails app services grails 下 class SessionService sta
  • Android相机无法从后台服务拍照

    我已经实现了一项从后台线程拍照的服务 但照片永远不会在我的任何设备上拍摄 这是代码 下面记录输出 public class PhotoCaptureService extends Service private static final S
  • 如何在 Docker-Compose 中一起使用主机网络和任何其他用户定义的网络?

    我想将 Docker Compose 文件中定义的两个 Docker 容器相互连接 app and db 其中之一 app 也应该连接到host网络 容器应连接到通用的用户定义网络 appnet or default 使用嵌入式DNS来自
  • Spring框架中的DAO和Service层到底是什么?

    Spring框架中的DAO和Service层到底是什么 我正在寻找理论答案 就 Spring 而言 没有区别 按照惯例 您可以使用以下方式标记 DAO 类 Repository和服务 Service 前者还进行一些持久层异常转换 既然您在理
  • 使用 MediaRecorder 录制屏幕特定视图

    我想录制特定的屏幕视频View链接只想记录里面执行的动作LinearLayout 现在 MediaRecorder正在录制整个屏幕 如何录制屏幕的特定部分 MediaRecorder 通过媒体投影API 记录整个屏幕 至少从 Android

随机推荐

  • 融合黄金正弦,十种混沌映射,搞定!把把最优值,本文思路可用于所有智能算法的改进...

    上一期的2023年最新优化算法之减法优化器算法 SABO 效果已经相当不错了 而且由于其十分简单的公式原理 更适用于刚接触智能优化算法的小伙伴 今天这篇文章为大家带来 融合黄金正弦的减法优化器 GSABO 本文会讲解一下改进思路 为各位小伙
  • 流程型和离散型制造行业mes系统的区别

    流程型和离散型制造行业mes系统的区别 在制造信息化的时代背景之下 MES系统 被越来越多的企业重视 虽然MES系统在制造行业中有着巨大的价值 但是不同的企业对MES系统的需求也存在很大的差异性 比较突出的就是流程型和离散型这两个方面 那么
  • 修改linux命令行终端的显示区行数列数

    stty rows 50 columns 200
  • Bugkuctf web 前女友

    老规矩 有新东西就记上一记 题目链接 这个有点儿意思 打开源码 好了 代码意思比较简单 重点看圈住的代码就好 满足v1v2的值不等但是md5相等 且v3 flag才行 好了 新知识来了 首先是md5 函数漏洞 第一种 GET a GET b
  • Web自动化Selenium-获取页面元素的相关信息

    获取页面元素的信息主要有两个目的 一是执行完步骤后进行断言 二是获取前一步骤的响应结果 将其作为后续步骤的输入或判断条件 获取元素的基本信息 目的输出元素的大小 文本 标签名 关键字 tag name 输出元素的标签名 size 输出元素的
  • TCP/IP协议,HTTP协议--面试必备

    经常面试被问到什么是http协议 什么是TCP协议 而且每次都弄不清楚 是时候记录一下了 一 什么是http协议 如果读者对计算机网络的体系结构比较了解的话应该清楚 IP协议位于网络层 TCP UDP协议位于传输层 HTTP位于应用层 如下
  • 本地存储基础

    本地存储特性 1 数据存储在用户浏览器中 2 设置 读取方便 甚至页面刷新不丢失数据 3 容量较大 sessionStorage约5M localStorage约20M 4 只能存储字符串 可以将对象JSON stringify 编码后存储
  • 如何使用Navicat修改mysql用户密码?

    https jingyan baidu com article 455a995054d490a167277858 html 下面介绍如何使用Navicat修改mysql用户密码的具体操作方法 工具 原料 Navicat Premium 方法
  • calico网络策略

    关于优先级order 为了与 Kubernetes 兼容 Calico 网络策略执行遵循 Kubernetes pod 的标准约定 如果没有网络策略适用于 Pod 则允许所有进出该 Pod 的流量 如果一个或多个网络策略应用于类型为 ing
  • TypeError: write() argument must be str, not bytes解决方法

    使用 HTMLTestRunner 输出测试报告 报错 TypeError write argument must be str not bytes 如下 原因 实例化HTMLTestRunner的runner runner HTMLTes
  • tmux插件管理器

    参考 tmux插件管理器tpm Tmux Plugin Manager 安装要求 tmux version 1 9以上 git bash 下载插件管理器 git clone https github com tmux plugins tpm
  • 2023Web自动化测试的技术框架和工具有哪些?

    Web 自动化测试是一种自动化测试方式 旨在模拟人工操作对 Web 应用程序进行测试 这种测试方式可以提高测试效率和测试精度 减少人工测试的工作量和测试成本 在 Web 自动化测试中 技术框架和工具起着至关重要的作用 本文将介绍几种常见的
  • linux实现复制文件的两种方法

    分享在linux系统下拷贝文件的两种方法 方法1 使用系统调用的read和write实现文件拷贝 include
  • 读书笔记: DetNet: Design Backbone for Object Detection

    读书笔记 DetNet Design Backbone for Object Detection 之前咱们不是读了adaptive convolution嘛 赶紧学以致用告诉我们为什么要用AC Abstract 背景 CNN已经被广泛应用于
  • android socket java_Android中Socket通信的实现方法概述

    本文实例简述了Android中Socket通信的实现方法 具体内容如下 一 socket通信概述 通俗的来说套接字 socket 是通信的基石 是支持TCP IP协议的网络通信的基本操作单元 它是网络通信过程中端点的抽象表示 包含进行网络通
  • 程序设计模式(二)创建型模式

    一 一个MAZE的构造过程 Maze的UML diagram如图所示 可以发现MapSite是斜体表示抽象类 有Room Door Wall三个子类继承 这三个就是用继承封装了MapSite的多向性 然而一个Maze 就是Room的聚合 所
  • JVM垃圾收集器-对比Serial、Parallel、CMS和G1

    4个Java垃圾收集器 错误的选择会对性能影响很大 现在很多开发者仍然搞不清垃圾收集器 这一块在Java 8版本的改动也比较大 特别是去掉了PermGen永久代和带来一些新的让人激动的优化 提到垃圾收集 大多数人在每天的编程工作中都会用到并
  • 从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入为0时结束程序。(题目类型:没有明确循环次数)

    import java util Scanner 从键盘读入个数不确定的整数 并判断读入的正数和负数的个数 输入 为0时结束程序 public class ForWhileTest public static void main Strin
  • 安卓手机免root本地运行青龙面板(ZeroTermux)

    安卓手机免root本地运行青龙面板 网盘下载 https www 123pan com s EZ6KVv J41Gd html提取码 4444 ZeroTermux https od ixcmstudio cn repository mai
  • Android进阶知识树——Android四大组件启动过程

    Android的四大钻无论对开发者或是用户都意义重大 对于用户来说应用就是Activity 用户所能看到的和交互的都发生在Activity中 对于开发者来说四大组件更是开发功能个展示功能的基础和媒介 对于初级开发者每天的工作都在和四大组件打