当前位置: 首页 > news >正文

宁波网站制作公司/济南最新消息今天

宁波网站制作公司,济南最新消息今天,政府部门网站建设需求,网络营销培训多少钱在手机桌面应用中点击某一个 icon 之后,最终是通过 startActivity 去打开某一个 Activity 页面。我们知道,Android 中的一个 APP 就相当于一个进程。所以,startActivity 操作中还需要判断,目标 Activity 的进程是否已经创建。如果…

在手机桌面应用中点击某一个 icon 之后,最终是通过 startActivity 去打开某一个 Activity 页面。我们知道,Android 中的一个 APP 就相当于一个进程。所以,startActivity 操作中还需要判断,目标 Activity 的进程是否已经创建。如果没有,则在显示 Activity 之前还需要将进程 Process 提前创建出来。

假设是从 Activity A 跳转到另一个 APP 中的 Activity B。过程如下图所示

整个 startActivity 的流程分为 3 大部分,也涉及 3 个进程之间的交互:

\bullet ActivityA --> ActivityManagerService(简称 AMS)

\bullet ActivityManagerService --> ApplicationThrad

\bullet ApplicationThread --> Activity

1. ActivityA 到 AMS 阶段

这一过程并不复杂,用如下这张图表示具体过程

接下来查看源码,看看做了哪些操作

Activity 的 startActivity(),最终调用了 startActivityForResult() 方法。传入的 -1 表示不需要获取 startActivity 的结果。

Activity 的 startActivityForResult(),具体代码如下所示。调用 Instrumentation 的 execStartActivity方法,剩下的交给 Instrumentation 类去处理。

Instrumentation 类主要用来监控应用程序与系统交互。蓝线部分的 MainThread 是 ActivityThread 类型。ActivityThread 可用理解为1个进程,这里即表示 ActivityA 所在的进程。通过 MainThread 获取一个 ApplicationThread 引用,这个引用就是实现进程间通信的。具体来说,就是 AMS 所在的系统进程通知应用进程进行了一系列操作。

Instrumentation 类的 execStartActivity。在 instrumentation 中会通过 ActivityManager.getService获取 AMS 的实例。然后,调用其 startActivity 方法。实际上这里就是通过 AIDL 来调用 AMS 的 startActivity 方法。

至此,startActivity 的工作重心成功的从进程 A 转移到了系统进程 AMS中。

2. ActivityManagerService 到 ApplicationThread 阶段

下面来探索在 AMS 中是如何一步一步执行到 B 进程的。

上面在讲 Instrumentation 时,我们提到了一个 ApplicationThread 类来负责进程间通信的。这里 AMS 最终其实就是调用了 B 进程的一个 ApplicationThread 引用,从而间接地通知 B 进程进行相应操作。

相比较 startActivity 到 AMS,AMS 到 ApplicationThread 的流程看起来复杂了很多。实际上,这里面就干了两件事情:

a):综合处理 launchMode 和 Intent 中的 Flag 标志位,并根据处理结果生成一个目标 Activity B 的对象(ActivityRecord);

b):判断是否需要为目标 Activity B 创建一个新的进程(ProcessRecord)、新的任务栈(TaskRecord)

AMS 的 startActivity

从上图中的代码可以看出,经过多个方法的调用,最终通过 obtainStarter() 方法获取了 ActivityStarter 类型的对象,然后调用其 execute() 方法。在 execute() 方法中,会再次调用其内部的 startActivityMayWait 方法。

ActivityStarter 的 startActivityMayWait 

ActivityStarter 类专门负责一个 Activity 的启动操作主要作用包括解析 Intent、创建 ActivityRecord、如果有可能还要创建 TaskRecord。

startActivityMayWait 的部分实现代码如下

从上面代码可以看出,获取目标 Activity 信息的操作由 mSupervisor 来实现,它是 ActivityStackSupervisor 类型。主要是负责 Activity 所处栈的管理类。在上面代码的 resolveIntent 中,实际上是调用系统 PackageManagerService 来获取最佳 Activity。有时候,我们通过隐式 Intent 启动 Activity 时,系统中可能存在多个 Activity 可以处理 Intent。此时会弹出一个选择框让用户选择具体需要打开哪一个 Activity 界面,就是此处的逻辑处理结果。

在 startActivityMayWait 方法中,调用了一个重载的 startActivity 方法,最终会调用 ActivityStarter 中的 startActivityUnchecked 方法来获取启动 Activity 的结果。

ActivityStarter 的 startActivityUnchecked

图中 1 处计算启动 Activity 的 Flag 值;图中2处处理 Task 和 Activity 的进栈操作;图中3处启动栈中顶部的 Activity。

\bullet computeLaunchingTaskFlags 方法

这个方法的主要作用是计算启动 Activity 的 Flag,不同的 Flag 决定了启动 Activity 最终会被放置到哪一个 Task 集合中。

图中1处 mInTask 是 TaskRecord 类型,此处为 null,代表 Activity 要加入的栈不存在。因此需要判断是否需要新建 Task;图中2处的 mSourceRecord 是 ActivityRecord 类型,它是用来描述初始 Activity(比如,ActivityA 启动了 ActivityB,ActivityA 就是初始 Activity)。当我们使用 Context 或者 Application 启动 Activity 时,此时 mSourceRecord 为 null;图中3处表示初始 Activity,如果是在 LAUNCH_SINGLE_INSTANCE 栈中的 Activity,需要添加 FLAG_ACTIVITY_NEW_TASK 的标识。因为 LAUNCH_SINGLE_INSTANCE 栈只能允许保存一个 Activity;图中4处表示,如果 LaunchMode 设置了 LAUNCH_SINGLE_TASK 或 LAUNCH_SINGLE_INSTANCE,则也要创建一个新栈。

\bullet startActivityLocked 方法

方法中会调用 insertTaskAtTop() 方法,尝试将 Task 和 Activity 入栈。如果 Activity 是以 NEW_TASK 的模式启动或者 Task 堆栈中不存在该 TaskId,则 task 会重新入栈并且放在栈的顶部。注意:Task 先入栈,之后才是 Activity 入栈,它们是包含关系。

上面一下子引出了好几个概念:Stack,Task,Activity。其实它们都是在 AMS 内部维护的数据结构,它们之间的关系如下图

\bullet  resumeFocusedStackTopActivityLocked 方法

经过一些列调用,最终代码又回到了 ActivitSupervisor 中

ActivityStackSupervisor 的 startSpecificActivityLocked 方法

图中1处根据进程名称和 Application 的 UID,来判断目标进程是否已经创建。如果没有,则代表进程未创建;图中2处调用 AMS 创建 Activity 所在进程。

不管是目标进程已经存在还是新建目标进程,最终都会调用图中红线部分的 realStartActivityLocked 方法来执行启动 Activity 的操作。

ActivityStackSupervisor 的 realStartActivityLocked 方法

这个方法在 Android 27 和 28两个版本的区别很大。从 android-28 开始 Activity 的启动交给了事务(Transaction)来完成。图中1处创建了 Activity 启动事务,并传入 app.thread 参数,它是 applicationThread 类型。在上文 startActivity 阶段,applicationThread 是为例实现进程间通信的,是 ActivityThread 的一个内部类;图中2处执行 Activity 的启动事务,由 ClientLifecycleManager 来完成。具体代码如下

可以看出,实际上是调用了启动事务的 ClientTransaction 的 schedule() 方法。而这个 transaction 实际上是在创建 ClientTransaction 时,传入的 app.thread 对象,也就是 applicationThrad。

这里传入的 app.thread 会赋值给 ClientTransaction 的成员变量 mClient,ClientTransaction 会调用 mClient.scheduleTransaction(this) 来执行事务。这个 app.thread 是 ActivityThread 的内部类 ApplicationThread,所以事务最终是调用 app.thread 的 scheduleTransaction 执行

 到这里位置,startActivity 的操作就成功的从 AMS 转移到了另一个进程B 中的 ApplicationThread 中。剩下的就是 AMS 通过进程间通信机制通知 ApplicationThread 执行 ActivityB 的生命周期方法。

3. ApplicationThread 到 Activity 阶段

上面我们分析到,AMS 将启动 Activity 的任务作为一个事务 ClientTransaction 去完成。在 ClientLifecycleManager 中会调用 ClientTransaction 的 schedule() 方法。如下代码所示

mClient 是一个 IApplicationThread 接口类型,具体实现是 ActivityThread 的内部类 ApplicationThread。因此,后续执行 Activity 生命周期的过程都是由 ApplicationThread 指导完成的。

上面代码中的 scheduleTransaction() 方法仍然是调用了 ActivityThread 的 scheduleTransaction() 方法,但实际上这个方法是在 ActivityThread 的父类 ClientTransactionHandler 中实现。

 调用 sendMessage() 方法向 Hanlder 中发送了一个 EXECUTE_TRANSACTION 消息,并且 Message 中的 obj 就是启动 Activity 的事务对象。而这个 Handler 的具体实现是 ActivityThread 中的 mH 对象。具体代码如下

最终调用了事务的 execute() 方法,如下代码所示

在 executeCallback 方法中,会遍历事务中的 callback 并执行 execute 方法。这些 callbacks 是何时被添加的呢?

前面在创建 ClientTransaction 时,通过 addCallback() 方法传入了callback 参数。从下面代码可以看出,其实是一个 LaunchActivityItem 对象

LaunchActivityItem 的 execute() 方法

这里就已经到了与 Activity 生命周期相关的方法。上面代码中的 client 是 ClientTransactionHandler 类型,实际实现类是 ActivityThread,因此最终方法又回到了 ActivityThread。

ActivityThread 的 handleLaunchActivity

这是一个比较重要的方法,Activity 的生命周期方法就是在这个方法中有序执行。

图中1处,初始化 Activity 的 WindowManager,每一个 Activity 都会对应一个窗口;图中2处,调用 performLaunchActivity 创建并显示 Activity;图中3处通过反射创建目标 Activity 对象;图中4处调用 attach 方法建立 activity 与 context 之间的联系。创建 phoneWindow 对象,并与 Activity 进行关联操作;图中5处通过 instrumentation 最终调用 Activity 的 onCreate 方法。

至此,目标 Activity 已经成功创建,并执行生命周期方法。

总结

本次详细介绍了 Activity 的启动在源码中的实现流程

这一过程主要涉及 3 个进程间的通信过程:

\bullet 进程 A 通过 Binder 调用 AMS 的 startActivity 方法;

\bullet AMS 通过一系列的计算构造目标 Intent,然后在 ActivityStack 与 ActivityStackSupervisor 中处理 Task 和 Activity 的入栈操作;

\bullet AMS 通过 Binder 机制,调用目标进程中 ApplicationThread 的方法来创建并执行 Activity 生命周期方法,ApplicationThread 是 ActivityThread 的一个内部类,最终都调用到了 ActivityThread 中的相应方法。

相关文章:

Android---StartActivity启动过程

在手机桌面应用中点击某一个 icon 之后,最终是通过 startActivity 去打开某一个 Activity 页面。我们知道,Android 中的一个 APP 就相当于一个进程。所以,startActivity 操作中还需要判断,目标 Activity 的进程是否已经创建。如果…...

隐私计算python实现Paillier同态加密

1.基本概念 Paillier同态加密是一种公钥加密方案,具有同态加密的特性。它由Pascal Paillier于1999年提出。 Paillier同态加密基于数论问题,其安全性基于大整数分解问题和离散对数问题的困难性。该方案可以用于保护隐私数据,同时支持在加密状态…...

代码随想录打卡第五十五天|● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组

300.最长递增子序列 **题目:**给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0…...

C# 创建Oceanbase ODBC数据源 DSN

需要管理员权限打开VS,因为只有管理员权限可以修改注册表 using Microsoft.Win32; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.Odbc; using System.Diagnostics; using System.Drawing;…...

C++ 常用函数汇总#include<algorithm>(3万字总结)

文章目录 1. 排序(Sorting)1.1 sort(first, last):对指定范围内的元素进行升序排序1.2 stable_sort(first, last):在保持相等元素的相对顺序的情况下对指定范围内的元素进行排序1.3 partial_sort(first, middle, last):对范围内的元素进行部分排序,使得前部分是最小的,但…...

Google Archive Patch 基础应用代码记录

项目地址 Google Archive Patch 前置 <!-- 差量应用模块 --> <dependency><groupId>com.google.archivepatcher</groupId><artifactId>archive-patch-applier</artifactId><version>1.0.4</version><scope>test</…...

机器学习——代价敏感错误率与代价曲线

文章目录 代价敏感错误率实现代价曲线例子 代价敏感错误率 指在分类问题中&#xff0c;不同类别的错误分类所造成的代价不同。在某些应用场景下&#xff0c;不同类别的错误分类可能会产生不同的代价。例如&#xff0c;在医学诊断中&#xff0c;将疾病患者错误地分类为健康人可…...

如何利用 ChatGPT 提升编程技能

目录 前言代码命名与 ChatGPT设计模式与 ChatGPT代码重构与 ChatGPT代码优化与 ChatGPTChatGPT 的潜在挑战与限制成功案例分析最佳实践与注意事项结语 前言 编程是一项充满创造性和挑战的任务&#xff0c;但也是一个需要花费大量时间和精力的领域。在日益复杂的软件开发环境中…...

ChatGPT:@EqualsAndHashCode(callSuper = false)是什么意思

ChatGPT&#xff1a;EqualsAndHashCode(callSuper false)是什么意思 EqualsAndHashCode(callSuper false)是什么意思&#xff1f; ChatGPT&#xff1a; EqualsAndHashCode(callSuper false) 是 Java 中的 Lombok 注解&#xff0c;用于自动生成 equals() 和 hashCode() 方法…...

docker部署的mariadb忘记密码

docker 里的 mariadb 数据库密码忘了&#xff0c;如果以前我会选择直接干掉重装&#xff0c;但是数据怎么办&#xff1f; 1 数据量小 就跳过密码登录进去备份出来 2 想办法改掉密码 我直接选择后者&#xff0c;跳过密码&#xff0c;mariadb10.4以后不能直接改密码了&#xff…...

一体化模型图像去雨+图像去噪+图像去模糊(图像处理-图像复原-代码+部署运行教程)

本文主要讲述了一体化模型进行去噪、去雨、去模糊&#xff0c;也就是说&#xff0c;一个模型就可以完成上述三个任务。实现了良好的图像复原功能&#xff01; 先来看一下美女复原.jpg 具体的&#xff1a; 在图像恢复任务中&#xff0c;需要在恢复图像的过程中保持空间细节…...

[java/力扣110]平衡二叉树——优化前后的两种方法

分析 根据平衡二叉树的定义&#xff0c;只需要满足&#xff1a;1、根节点两个子树的高度差不超过1&#xff1b;2、左右子树都为平衡二叉树 代码 public class BalancedBinaryTree {public class TreeNode{int val;TreeNode left;TreeNode right;TreeNode(){}TreeNode(int va…...

吉他、班卓琴和贝斯吉他降分器:Arobas Music Guitar 8.1.1

Arobas Music Guitar 是一款专业的吉他、班卓琴和贝斯吉他降分器。在熟练的手中&#xff0c;它不仅可以让您创作&#xff0c;还可以编辑、聆听和录制&#xff0c;以及导入和导出乐谱。如果有人感兴趣的话&#xff0c;录音是在八个轨道上进行的&#xff0c;你可以为每个轨道单独…...

cocos tilemap的setTileGIDAt方法不实时更新

需要取消勾选 Enable Culling。同时代码添加&#xff1a;markForUpdateRenderData函数。 floor.setTileGIDAt(102427,newP.x,newP.y,0); //中心 floor.markForUpdateRenderData(); 具体问题参考官网说明&#xff1a; Cocos Creator 3.2 手册 - 项目设置...

机器学习---使用 TensorFlow 构建神经网络模型预测波士顿房价和鸢尾花数据集分类

1. 预测波士顿房价 1.1 导包 from __future__ import absolute_import from __future__ import division from __future__ import print_functionimport itertoolsimport pandas as pd import tensorflow as tftf.logging.set_verbosity(tf.logging.INFO) 最后一行设置了Ten…...

铁合金电炉功率因数补偿装置设计

摘要 由于国内人民生活水平的提高&#xff0c;科技不断地进步&#xff0c;控制不断地完善&#xff0c;从而促使功率因数补偿装置在电力等系统领域占据主导权&#xff0c;也使得功率因数补偿控制系统被广泛应用。在铁合金电炉系统设计领域中&#xff0c;功率因数补偿控制成为目前…...

表格识别软件:科技革新引领行业先锋,颠覆性发展前景广阔

表格识别软件的兴起背景可以追溯到数字化和自动化处理的需求不断增加的时期。传统上&#xff0c;手动处理纸质表格是一项费时费力的工作&#xff0c;容易出现错误&#xff0c;效率低下。因此&#xff0c;开发出能够自动识别和提取表格数据的软件工具变得非常重要。 随着计算机…...

【Redis】高并发分布式结构服务器

文章目录 服务端高并发分布式结构名词基本概念评价指标1.单机架构缺点 2.应用数据分离架构应用服务集群架构读写分离/主从分离架构引入缓存-冷热分离架构分库分表&#xff08;垂直分库&#xff09;业务拆分⸺微服务 总结 服务端高并发分布式结构 名词基本概念 应⽤&#xff0…...

微信小程序拍照页面自定义demo

api文档 <template><div><imagemode"widthFix"style"width: 100%; height: 300px":src"imageSrc"v-if"imageSrc"></image><camerav-else:device-position"devicePosition":flash"flash&qu…...

单目标应用:进化场优化算法(Evolutionary Field Optimization,EFO)求解微电网优化MATLAB

一、微网系统运行优化模型 微电网优化模型介绍&#xff1a; 微电网多目标优化调度模型简介_IT猿手的博客-CSDN博客 二、进化场优化算法EFO 进化场优化算法&#xff08;Evolutionary Field Optimization&#xff0c;EFO&#xff09;由Baris Baykant Alagoz等人于2022年提出&…...

推荐算法面试

当然可以&#xff0c;请看下面的解释和回答&#xff1a; 一面&#xff08;7.5&#xff09; 问题&#xff1a;推荐的岗位和其他算法岗&#xff08;CV&#xff0c;NLP&#xff09;有啥区别&#xff1f; 解释&#xff1a; 面试官可能想了解你对不同算法岗位的理解&#xff0c;包…...

长图切图怎么切

用PS的切片工具 切片工具——基于参考线的切片——ctrl&#xff0b;shift&#xff0b;s 过长的图片怎么切 ctrl&#xff0b;alt&#xff0b;i 查看图片的长宽看图片的长宽来切成两个板块&#xff08;尽量中间切成两半&#xff09;用选区工具选中下半部分的区域——在选完时不…...

动手学深度学习 - 学习环境配置

学习环境配置 1、安装 Miniconda1.1 下载 miniconda31.2 环境变量配置1.3 安装成功测试1.4 配置文件1.5 使用conda创建、使用、删除环境1.6 conda 常用命令 2、使用 miniconda 安装 d2l2.1 下载 d2l 安装包2.2 安装 d2l 1、安装 Miniconda 参考&#xff1a; https://www.jb51.n…...

洛谷 B2004 对齐输出 C++代码

目录 推荐专栏 题目描述 AC Code 切记 推荐专栏 http://t.csdnimg.cn/Z1tCAhttp://t.csdnimg.cn/Z1tCA 题目描述 题目网址&#xff1a;对齐输出 - 洛谷 AC Code #include<bits/stdc.h> using namespace std; typedef long long ll; int main() { int a,b,c;cin&g…...

seccomp学习 (1)

文章目录 0x01. seccomp规则添加原理A. 默认规则B. 自定义规则 0x02. seccomp沙箱“指令”格式实例Task 01Task 02 0x03. 总结 今天打了ACTF-2023&#xff0c;惊呼已经不认识seccomp了&#xff0c;在被一道盲打题折磨了一整天之后&#xff0c;实在是不想面向题目高强度学习了。…...

Linux指令【上】

目录 目录结构 ls cd stat touch mkdir whoami 查看当前帐号是谁 who 查看当前有哪些人在使用 pwd 当前的工作目录 目录结构 目录结构就是一颗多叉树的样子 路径 我们从 / 目录开始&#xff0c;定位一个叶子文件的…...

RK3568-clock

pll锁相环 总线 gating rk3568.dtsi pmucru: clock-controller@fdd00000 {compatible = "rockchip,rk3568-pmucru";reg = <0x0 0xfdd00000 0x0 0x1000>;rockchip,grf = <&grf>;rockchip,pmugrf = <&pmugrf>;#clock-cells = <1>;#re…...

新恶意软件使用 MSIX 软件包来感染 Windows

人们发现&#xff0c;一种新的网络攻击活动正在使用 MSIX&#xff08;一种 Windows 应用程序打包格式&#xff09;来感染 Windows PC&#xff0c;并通过将隐秘的恶意软件加载程序放入受害者的 PC 中来逃避检测。 Elastic Security Labs 的研究人员发现&#xff0c;开发人员通常…...

干货!数字IC后端入门学习笔记

很多同学想要了解IC后端&#xff0c;今天大家分享了数字IC后端的学习入门笔记&#xff0c;供大家学习参考。 很多人对于后端设计的概念比较模糊&#xff0c;需要做什么也都不甚清楚。 有的同学认为就是跑跑 flow、掌握各类工具。 事实上&#xff0c;后端设计的工作远不止于此。…...

力扣:144. 二叉树的前序遍历(Python3)

题目&#xff1a; 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 示例&#xff1a; 示例 1&#xff1a; 输…...