Android中的冷启动,热启动和温启动

ops/2024/9/20 3:54:50/ 标签: android

在App启动方式中分为三种:冷启动(cold start)、热启动(hot start)、温启动(warm start)

冷启动:

系统不存在App进程(App首次启动或者App被完全杀死)时启动App(后台没有该应用的进程,这时系统会又一次创建一个新的进程分配给该应用),此时,App的启动将经历两个阶段:

第一阶段:

1.加载并启动app
2.app启动后,第一时间为app显示一个空白的window
3.创建app进程

第二阶段:

系统一旦创建了app进程,app进程就要负责做以下的任务:
1.创建app对象
2.创建ActivityThread
3.创建MainActivity
4.渲染视图
5.执行onLayout
6.执行onDraw
7.完成第一次绘制后,把mainActivity替换已经展示的BackgroundWindow,即空白window。

也就是说冷启动由于系统会又一次创建一个新的进程分配给它。所以会先创建和初始化Application类,再创建和初始化MainActivity类(包含一系列的測量、布局、绘制),最后显示在界面上。

ActivityThread:负责管理应用程序的生命周期,处理消息队列,处理用户输入事件,调度Activity的创建和销毁等等。
具体来说,ActivityThread会在应用程序启动时会创建一个主线程(也就是UI线程),然后根据AndroidManifest.xml文件中声明的启动Activity,创建一个Activity对象,并通过Binder机制将这个Activity对象传递给ActivityManagerService。Activity还会负责处理Activity的生命周期,比如当用户按下返回键退出当前Activity时,ActivityThread会收到相应的消息,然后销毁当前Activity并恢复上一个Activity的状态。ActivityThread还负责处理其他一些系统事件,比如屏幕旋转、系统资源不足等等,这些事件都会通过消息队列传递给ActivityThread,然后由ActivityThread调度处理。

温启动

温启动包含在冷启动期间发生的一些操作,它的开销大于热启动(重新走 Activity 的一些生命周期,它不会重新走进程的创建、Application 的生命周期等)。由于app进程依然在,温启动只执行冷启动的第二阶段。例如:

  • 比如返回Home后,又继续使用其他的APP,时间久了或者打开的应用多了,之前应用的Activity有可能被回收了,但应用程序必须通过调用 onCreate() 重新创建Activity
  • 应用程序因为内存原因被系统强制退出,然后用户重新启动应用。进程和 Activity 需要被重新启动,但是保存的 Bundle 实例状态会被传递给 onCreate() 使用

热启动

热启动比冷启动简单得多而且开销更低,在热启动时,系统会将Activity从后台切回到前台,如果应用的所有Activity仍旧留在内存中,那么应用可以避免重复创建对象初始化,布局加载和绘制。
如果应用响应了系统内存清理的通知清理了内存,比如回调onTrimMemory(),那么这些被清理的对象在热启动就会被重新创建。也就和冷启动展示在屏幕的行为相同,系统进程会创建一个空白的屏幕直到应用绘制完成显示出Activity。

App启动优化

app启动优化的方向是冷启动。

空白window问题

app启动时,会短暂的一瞬间白屏:
在这里插入图片描述
这是我在Application的onCreate里线程休眠1s实现的。但是在实际项目中确实会存在启动白屏时间过长的问题。
为什么会有白屏?看app启动流程加载首屏部分源码:
ActivityStack

// Set to false to disable the preview that is shown while a new activity// is being started.private static final boolean SHOW_APP_STARTING_PREVIEW = true;void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,boolean newTask, boolean keepCurTransition, ActivityOptions options) {//…… 省略一万行……if (!isHomeOrRecentsStack() || numActivities() > 0) {if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,"Prepare open transition: starting " + r);//…… 省略一万行……boolean doShow = true;if (newTask) {// Even though this activity is starting fresh, we still need// to reset it to make sure we apply affinities to move any// existing activities from other tasks in to it.// If the caller has requested that the target task be// reset, then do so.if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {resetTaskIfNeededLocked(r, r);doShow = topRunningNonDelayedActivityLocked(null) == r;}} else if (options != null && options.getAnimationType()== ActivityOptions.ANIM_SCENE_TRANSITION) {doShow = false;}if (r.mLaunchTaskBehind) {// Don't do a starting window for mLaunchTaskBehind. More importantly make sure we// tell WindowManager that r is visible even though it is at the back of the stack.r.setVisibility(true);ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);// 如果同时满足,则显示空白屏幕} else if (SHOW_APP_STARTING_PREVIEW && doShow) {//……//显示空白屏幕r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));}} else {// If this is the first activity, don't do any fancy animations,// because there is nothing for it to animate on top of.ActivityOptions.abort(options);}}

在源码在可以看到,显示白屏由两个变量决定SHOW_APP_STARTING_PREVIEW && doShow,SHOW_APP_STARTING_PREVIEW 表示activity启动前是否显示预览;doShow,其默认值为true,但是它由newTask决定,是否为一个全新的activity栈,也就是说,SHOW_APP_STARTING_PREVIEW为true,并且app冷启动,就显示白屏。
那么能不能让用户不显示白屏呢?
由两种方法:
1.禁用app启动时window预览的功能
在主题中为首屏activity添加一个注意禁用window预览的功能,并在manifest中使用

<resources><!--Base application theme--><style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"><!--Customize your theme here.--><item name="colorPrimary">@color/mainColor</item><item name="colorPrimaryDark">@color/red</item><item name="colorAccent">@color/black</item></style><!--禁用预览功能主题--><style name="AppSpalshNoPreviewTheme" parent="AppTheme"><item name="android:windowFullscreen">true</item><item name="windowNoTitle">true</item><!--        <item name="android:windowContentOverlay">@null</item>--><!--        <item name="android:windowBackground">@mipmap/wall</item>--><item name="android:windowDisablePreview">true</item></style>
</resources>

在这里插入图片描述
这个时候你会发现点击了app,过了1秒多才启动,因为我们让本来显示的空白预览页面不展示了。
2.给空白首屏Activity设置一个背景
在style.xml中给SplashActivity添加一个新主题,设置一个背景:

    <style name="AppSpalshNoPreviewTheme" parent="AppTheme"><item name="android:windowBackground">@mipmap/aliyun</item><item name="android:windowFullscreen">true</item><item name="windowNoTitle">true</item>
<!--        <item name="android:windowDisablePreview">true</item>--></style>

在这里插入图片描述
会发现点击了之前的空白页面换成了背景图。
从上面冷启动的介绍可知,app启动过程中,会有如下过程
在这里插入图片描述
app启动过程中,显示白屏,首屏第一次绘制完成,就会替换白屏。也就是说在首屏显示之前,都是白屏。
所以,要想解决白屏的问题,就要减少白屏显示的时间,也就是说要加快app初始化和首屏绘制的时间。


http://www.ppmy.cn/ops/112117.html

相关文章

谷歌-BERT-“bert-base-chinese ”

1 需求 2 接口 3 示例 4 参考资料 在Hugging Face上下载并使用Bert-base-Chinese_bert-base-chinese下载-CSDN博客 3 文本分类入门finetune&#xff1a;bert-base-chinese-CSDN博客 4如何对BERT 微调-案例_tokenizer input max length: 1000000000000000019884-CSDN博客 基…

python AssertionError: Torch not compiled with CUDA enabled

查看&#xff1a;torch import torch# 输出带CPU&#xff0c;表示torch是CPU版本的 print(ftorch的版本是&#xff1a;{torch.__version__}) # print(ftorch是否能使用cuda&#xff1a;{torch.cuda.is_available()}) 修改一下代码&#xff0c;将cuda改成cpu 最后运行正常&…

LINUX网络编程:http

目录 1.认识http请求的字段 2.HTTP请求类 3.认识HTTP应答字段 4.HTTP应答类 5.源代码 协议就是一种约定&#xff0c;http也并不例外&#xff0c;使用http也无非就是&#xff0c;定义一个http请求的结构体&#xff0c;将结构体序列化为字符串&#xff0c;发送给服务器&…

SpringBoot2:web开发常用功能实现及原理解析-上传与下载

文章目录 一、上传文件1、前端上传文件给Java接口2、Java接口上传文件给Java接口 二、下载文件1、前端调用Java接口下载文件2、Java接口下载网络文件到本地3、前端调用Java接口下载网络文件 一、上传文件 1、前端上传文件给Java接口 Controller接口 此接口支持上传单个文件和…

【Kubernetes】常见面试题汇总(二十)

目录 62.简述 Kubernetes Pod 如何实现对节点的资源控制&#xff1f; 63.简述 Kubernetes Requests 和 Limits 如何影响 Pod 的调度&#xff1f; 64.简述 Kubernetes Metric Service &#xff1f; 62.简述 Kubernetes Pod 如何实现对节点的资源控制&#xff1f; - Kubernete…

自定义spring security的安全表达式

在Spring Security中&#xff0c;DefaultMethodSecurityExpressionHandler是处理方法安全表达式的默认处理器。如果你想注册自定义的安全表达式方法&#xff0c;你需要创建一个自定义的表达式处理器&#xff0c;继承自DefaultMethodSecurityExpressionHandler&#xff0c;并重写…

数组学习内容

动态初始化 只给长度&#xff0c;数据类型【】 数组名new 数据类型【数组长度】 内存图

TensorFlow 2.0 快速入门——手把手学会训练模型

目录 文章灵感 快速入门 代码解释 快速入门代码 加载数据集 构建机器学习模型 损失函数和编译模型 训练并评估模型 修改模型以返回概率 运行效果解释 我的修改 保存我们训练好的模型 代码解释 1. 加载 MNIST 数据集 2. 数据预处理&#xff08;归一化&am…

matlab fid = fopen(file_nav,‘rt‘);语句解释

fopen 函数 fopen 是一个 MATLAB 函数&#xff0c;用于打开文件并返回一个文件标识符&#xff08;file identifier&#xff09;&#xff0c;该标识符用于后续的文件操作。 参数 file_nav file_nav 是一个变量&#xff0c;包含要打开的文件的名称或路径。它通常是一个字符串&…

微信小程序页面制作——婚礼邀请函(含代码)

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

第十章 【后端】环境准备(10.9)——Navicat

10.9 Navicat Navicat Premium 官网 下载 下载地址:https://www.navicat.com.cn/download/navicat-premium-lite 安装 一路“下一步”即可。 连接 `MySql’

SOMEIP_ETS_113: SD_Empty_Options_Array

测试目的&#xff1a; 验证DUT能够拒绝一个选项数组长度为0的SubscribeEventgroup消息&#xff0c;并以SubscribeEventgroupNAck作为响应。 描述 本测试用例旨在确保DUT遵循SOME/IP协议&#xff0c;当接收到一个选项数组长度为0的SubscribeEventgroup消息时&#xff0c;能够…

Google推出Data Commons解决AI“幻觉”

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

MATLAB系列06:复数数据、字符数据和附加画图类

MATLAB系列06&#xff1a;复数数据、字符数据和附加画图类 6. 复数数据、字符数据和附加画图类6.1 复数数据6.1.1 复变量&#xff08; complex variables&#xff09;6.1.2 带有关系运算符的复数的应用6.1.3 复函数&#xff08; complex function&#xff09;6.1.4 复数数据的作…

您的计算机已被.lcrypt勒索病毒感染?恢复您的数据的方法在这里!

导言 在网络安全领域&#xff0c;勒索病毒已经成为一种威胁极大的恶意软件&#xff0c;其中.lcrypt勒索病毒&#xff08;.lcrypt ransomware&#xff09;是最近出现的一种新的变种。它以加密用户数据并要求赎金为手段&#xff0c;严重影响个人和组织的日常运营。本文91数据恢复…

Django学习实战篇四(适合略有基础的新手小白学习)(从0开发项目)

前言&#xff1a; 在本章中&#xff0c;我们开始编写面向用户的界面&#xff0c;其中只涉及简单的HTML结构&#xff0c;不会做太多美化&#xff0c;目的就是把后台创建的数据展示到前台。 从技术上来讲&#xff0c;这一节将涉及Django 中function view和 class-based view 的用…

堆排序,快速排序

目录 1.堆排序 2.快速排序 1.hoare版本 2.挖坑法 3.前后指针法 注意点 1.堆排序 void Swap(int* a, int* b) {int tmp *a;*a *b;*b tmp; } void adjustdown(int* a, int n, int parent) {int child parent * 2 1;while (child < n){if (child 1 < n &&am…

raksmart的G口大流量服务器怎么样?

RAKsmart的G口大流量服务器以其高性能、高可用性、灵活配置和全球覆盖等特点&#xff0c;成为许多企业和个人用户的理想选择。以下是对raksmart G口大流量服务器的具体介绍&#xff1a; 1. 服务特点&#xff1a; RAKsmart提供多种类型的G口大流量服务器&#xff0c;包括流媒体专…

华为ensp中vlan与静态路由技术的实现

vlan 同一网段的设备&#xff0c;可以互通&#xff1b; 虚拟局域网&#xff1a;将局域网从逻辑上划分为多个局域网&#xff0c;不同通过vlan编号区分&#xff1b; 实现网络隔离。提高了网络安全性&#xff1b; vlan编号为12位&#xff1b; 范围1-4094可以用来配置 默认处于…

【Qt系列样式表】探索Qt Widget的艺术化设计与应用(Macos风格)(持续更新中...)

✨✨ Rqtz 个人主页 : 点击✨✨ &#x1f308;Qt系列专栏:点击 &#x1f388;PyQt系列专栏:点击&#x1f388; &#x1f388;Qt智能车上位机专栏: 点击&#x1f388; &#x1f388;Qt串口助手专栏:点击&#x1f388; &#x1f4ab;宗旨:共享IT之美,共创机器未来 目录 界面…