Android 性能优化—— 启动优化提升60%

news2025/1/19 20:42:17

img

应用启动速度

一个应用App的启动速度能够影响用户的首次体验,启动速度较慢(感官上)的应用可能导致用户再次开启App的意图下降,或者卸载放弃该应用程序

本文将从两个方向优化应用的启动速度 :

1.视觉体验优化 2.代码逻辑优化

视觉优化

应用程序启动有三种状态,每种状态都会影响应用程序对用户可见所需的时间:冷启动,热启动和温启动

关于这3种启动方式,可以查看谷歌开发文档

大家常说的是冷启动和热启动

1.冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动 2.热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动

在冷启动时,应用程序从头开始。在其他状态下,系统需要将正在运行的应用程序从后台运行到前台。我们建议您始终根据冷启动的假设进行优化。这样做也可以改善热启动和温启动的性能

在冷启动开始时,系统有三个任务。这些任务是:

1.加载并启动应用程序 2.启动后立即显示应用程序空白的启动窗口 3.创建应用程序进程

一旦系统创建应用程序进程,应用程序进程就会负责下一阶段,这些阶段包括:

1.创建app对象 2.启动主线程(main thread) 3.填充加载布局Views 4.在屏幕上执行View的绘制过程.measure -> layout -> draw

应用程序进程完成第一次绘制后,系统进程会交换当前显示的背景窗口,将其替换为主活动。此时,用户可以开始使用该应用程序

img

因为App应用进程的创建过程是由手机的软硬件决定的,所以我们只能在这个创建过程中视觉优化

启动主题优化

所谓的主题优化,就是应用程序在冷启动的时候(1~2阶段),设置启动窗口的主题

因为现在 App 应用启动都会先进入一个闪屏页(LaunchActivity) 来展示应用信息

默认情况下会出现白屏现象,系统默认会在启动应用程序的时候 启动空白窗口 ,直到 App 应用程序的入口 Activity 创建成功,视图绘制完毕系统默认会在启动应用程序的时候 启动空白窗口 ,直到 App 应用程序的入口 Activity 创建成功,视图绘制完毕系统默认会在启动应用程序的时候 启动空白窗口 ,直到 App 应用程序的入口 Activity 创建成功,视图绘制完毕

解决方法可查看Android启动界面SplashActivit的实现方法

代码优化

Android中如何计算 App 的启动时间

根据上面启动时间的输出统计,我们就可以先记录优化前的冷启动耗时,然后再对比优化之后的启动时间

Application 优化

Application 作为 应用程序的整个初始化配置入口,时常担负着它不应该有的负担~

有很多第三方组件(包括App应用本身)都在 Application 中抢占先机,完成初始化操作

但是在 Application 中完成繁重的初始化操作和复杂的逻辑就会影响到应用的启动性能

通常,有机会优化这些工作以实现性能改进,这些常见问题包括:

1.复杂繁琐的布局初始化 2.阻塞主线程 UI 绘制的操作,如 I/O 读写或者是网络访问 3.Bitmap 大图片或者 VectorDrawable加载 4.其它占用主线程的操作

我们可以根据这些组件的轻重缓急之分,对初始化做一下分类

1.必要的组件一定要在主线程中立即初始化(入口 Activity 可能立即会用到) 2.组件一定要在主线程中初始化,但是可以延迟初始化 3.组件可以在子线程中初始化

**放在子线程的组件初始化建议延迟初始化 **,这样就可以了解是否会对项目造成影响

所以对于上面的分析,我们可以在项目中 Application 的加载组件进行如下优化 :

  • 将Bugly,x5内核初始化,SP的读写,友盟等组件放到子线程中初始化。(子线程初始化不能影响到组件的使用)
new Thread(new Runnable() {
            @Override
            public void run() {
                //设置线程的优先级,不与主线程抢资源
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                //子线程初始化第三方组件
                Thread.sleep(5000);//建议延迟初始化,可以发现是否影响其它功能,或者是崩溃!
            }
        }).start();
  • 将需要在主线程中初始化但是可以不用立即完成的动作延迟加载(原本是想在入口 Activity 中进行此项操作,不过组件的初始化放在 Application 中统一管理为妙)
handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //延迟初始化组件
            }
        }, 3000);

闪屏页业务优化

最后还剩下那些为数不多的组件在主线程初始化动作,例如埋点,点击流,数据库初始化等,不过这些消耗的时间可以在其它地方相抵

需求背景: 应用App通常会设置一个固定的闪屏页展示时间,例如2000ms,所以我们可以根据用户手机的运行速度,对展示时间做出调整,但是总时间仍然为 2000ms

闪屏页展示总时间 = 组件初始化时间 + 剩余展示时间

也就是2000ms的总时间,组件初始化了800ms,那么就再展示1200ms即可

Application 初始化后会调用 attachBaseContext() 方法,再调用 Application 的 onCreate(),再到入口 Activity的创建和执行 onCreate() 方法。所以我们就可以在 Application 中记录启动时间

//Application
@Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        SPUtil.putLong("application_attach_time", System.currentTimeMillis());//记录Application初始化时间
    }

有了启动时间,我们得知道入口的 Acitivty 显示给用户的时间(View绘制完毕),在onWindowFocusChanged()的回调时机中表示可以获取用户的触摸时间和View的流程绘制完毕,所以我们可以在这个方法里记录显示时间

//Activity
@Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
  
          long appAttachTime = SPUtil.getLong("application_attach_time");
          long diffTime = System.currentTimeMillis() - appAttachTime;//从application到入口Acitity的时间
 
         //所以闪屏页展示的时间为 2000ms - diffTime.
    }

所以我们就可以动态的设置应用闪屏的显示时间,尽量让每一部手机展示的时间一致,这样就不会让手机配置较低的用户感觉漫长难熬的闪屏页时间(例如初始化了2000ms,又要展示2000ms的闪屏页时间.),优化用户体验

广告页优化

闪屏页过后就要展示金主爸爸们的广告页了

因为项目中广告页图片有可能是大图,APng动态图片,所以需要将这些图片下载到本地文件,下载完成后再显示,这个过程往往会遇到以下两个问题 :

  • 广告页的下载,由于这个是一个异步过程,所以往往不知道加载到页面的合适时机
  • 广告页的保存,因为保存是 I/O 流操作,很有可能被用户中断,下次拿到破损的图片

因为不清楚用户的网络环境,有些用户下载广告页可能需要一段时间,这时候又不可能无限的等候。所以针对这个问题我们可以开启 IntentService 用来下载广告页图片

在入口 Acitivity 中开启 IntentService 来下载广告页。 或者是其它异步下载操作

在广告页图片 文件流完全写入后 记录图片大小,或者记录一个标识

在下次的广告页加载中可以判断是否已经下载好了广告页图片以及图片是否完整,否则删除并且再次下载图片

另外因为在闪屏页中仍然有 剩余展示时间,所以在这个时间段里如果用户已经下载好了图片并且图片完整,就可以显示广告页。否则进入主 Activity , 因为 IntentService 仍然在后台继续默默的下载并保存图片~

最后

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。

更多Android进阶指南 可以扫码 解锁 《Android十大板块文档》

1.Android车载应用开发系统学习指南(附项目实战)

2.Android Framework学习指南,助力成为系统级开发高手

3.2023最新Android中高级面试题汇总+解析,告别零offer

4.企业级Android音视频开发学习路线+项目实战(附源码)

5.Android Jetpack从入门到精通,构建高质量UI界面

6.Flutter技术解析与实战,跨平台首要之选

7.Kotlin从入门到实战,全方面提升架构基础

8.高级Android插件化与组件化(含实战教程和源码)

9.Android 性能优化实战+360°全方面性能调优

10.Android零基础入门到精通,高手进阶之路

敲代码不易,关注一下吧。ღ( ´・ᴗ・` ) 🤔

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1051763.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring Framework 学习笔记4:AOP

Spring Framework 学习笔记4:AOP 1.概念 AOP(Aspect Oriented Programming,面向切面编程)是一种编程思想。它要解决的问题是:如何在不改变代码的情况下增强代码的功能。 AOP 有一些核心概念: 连接点&am…

OpenGL之光照贴图

我们需要拓展之前的系统,引入漫反射和镜面光贴图(Map)。这允许我们对物体的漫反射分量和镜面光分量有着更精确的控制。 漫反射贴图 我们希望通过某种方式对物体的每个片段单独设置漫反射颜色。我们仅仅是对同样的原理使用了不同的名字:其实都是使用一张…

5.图形的连续绘制

到目前为止我们已经学习了折线,圆弧,矩形的基本绘制,但是我们每次都是单独绘制并且只绘制一个图形的。 不知道大家有没有试过在一个画布上绘制多个图形,例如我现在要画一个矩形,一个圆形和一段折线,代码如下…

03. 人工智能核心基础 - 导论(2)

文章目录 从方法论上来讲从问题范式上来讲从研究对象来讲 Hi,你好。我是茶桁。 上一章中,我们谈论了人工智能在时间维度上的不同时间不同的侧重点,这只是一个片面的方面。当然除此之外,我们还要从其他方向来认识人工智能&#xf…

解决大模型行业落地三大挑战,华为云GaussDB向量数据库正式发布

随着AI大模型产品及应用呈现爆发式增长,新的AI时代已经到来。向量数据库可与大语言模型配合使用,解决大模型落地过程中的痛点,已成为企业数据处理和应用大模型的必选项。在近日举行的华为全联接大会2023期间,华为云正式发布GaussDB向量数据库。GaussDB向量数据库基于GaussD…

python:bottle + eel 模仿 mdict 查英汉词典

Eel 是一个轻量的 Python 库,用于制作简单的类似于离线 HTML/JS GUI 应用程序,并具有对 Python 功能和库的完全访问权限。 Eel 托管一个本地 Web 服务器,允许您使用 Python 注释函数(annotate functions),…

IDLE、Anaconda安装与使用

博主:命运之光 专栏:Python程序设计​​​​​ 目录 Python下载和安装 Anaconda安装和使用 Python程序运行方式 Python下载和安装 常用集成开发环境 IDE 默认编程环境: IDLE---初学者( Download Python | Python.org &#x…

自动群发节日祝福,1 行 Python 代码搞定,小白可用

想了解更多精彩内容,快来关注程序员晚枫 大家节日快乐,这里是程序员晚枫,小红薯也叫这个名字。 今天给大家分享一个实用功能:自动群发祝福消息。 我相信社会人都体会过,过年过节给别人群发祝福消息的无奈&#xff0…

前沿研究|16s+宏基因组binning揭示大型藻类附生微生物群落核心组成

发表期刊:Microbiome 发表时间:2023 影响因子:15.5 DOI: 10.1186/s40168-023-01559-1 研究背景 大型藻类附生微生物群落是新型酶类和化合物的丰富资源,在维持沿海系统的高生物生产力和生物多样性方面发挥着重要的作用。但迄今…

华为乾坤区县教育安全云服务解决方案(2)

本文承接: https://blog.csdn.net/qq_37633855/article/details/133276200?spm1001.2014.3001.5501 重点讲解华为乾坤区县教育安全云服务解决方案的部署流程。 华为乾坤区县教育安全云服务解决方案(2) 课程地址解决方案部署整体流程组网规划…

Prettier - Code formatter格式化规则文件

文章目录 前言安装使用 前言 先前公司在规范代码时,由于个人业务繁忙跟技术总监是后端出身用的IDEA不熟悉vsCode;以及大多数时都自己一个人负责一个项目,当时并不看重这些;最近在整理vue3tsvite的脚手架模板(平时工作用的react),开始整理格式化代码,方便之后 vue 和 react 中应…

(附源码)springboot体检预约APP 计算机毕设16370

目 录 摘要 1 绪论 1.1开发背景 1.2研究现状 1.3springboot框架介绍 1.4论文结构与章节安排 2 Springboot体检预约APP系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统流程分析 2.2.1 数据添加流程 2.2.2 数据…

什么是Promise链(Promise chaining)?它在异步编程中的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是 Promise 链?⭐ 异步编程中的作用⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、…

Java后端接口编写流程

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! Java后端接口编写流程 Java后端接口编写流程,更具业务逻辑编写Java后端接口,提供给前端访问 实现逻辑流程 POJO:实体类编写 Data B…

架构设计第七讲:数据巡检系统之daily线上表结构自动化比对

架构设计第七讲:数据巡检系统之daily&线上表结构自动化比对 本文是架构设计第七讲,数据巡检系统之daily&线上表结构自动化比对,避免正式环境与测试环境数据库/表、列结构不一致带来问题。 文章目录 架构设计第七讲:数据巡…

36 二叉树中序遍历

二叉树中序遍历 题解1 递归题解2 迭代 给定一个二叉树的根节点 root &#xff0c;返回它的 中序 遍历 。 提示&#xff1a; 树中节点数目在范围 [0, 100] 内-100 < Node.val < 100 进阶: 递归算法很简单&#xff0c;你可以通过迭代算法完成吗&#xff1f; 题解1 递归…

Python绘图系统23:导入多个坐标轴的数据

文章目录 单轴导入多轴导入多文件导入合并导入源代码 Python绘图系统&#xff1a; 前置源码&#xff1a; Python打造动态绘图系统&#x1f4c8;一 三维绘图系统 &#x1f4c8;二 多图绘制系统&#x1f4c8;三 坐 标 轴 定 制&#x1f4c8;四 定制绘图风格 &#x1f4c8;五 数据…

第一章 数据可视化和matplotlib

Python数据可视化 第一章 数据可视化和matplotlib 1.数据可视化概述 1.1.什么是数据可视化 ​ 数据可视化旨在借助图形化的手段&#xff0c;将一组数据以图形的形式表示&#xff0c;并利用数据分析和开发工具发现其中未知信息的处理过程。 ​ 数据可视化发展历史 ​ 可视化…

Spring IOC容器实例化Bean整体流程图

SpringBean实例化的基本流程-CSDN博客 Spring容器中的BeanDefinitionReader读取器&#xff0c;读取xml配置文件&#xff0c;解析每一个bean标签&#xff0c;将bean标签中信息封装到BeanDefinition对象中&#xff0c;该对象的集合存储到BeanDefinitionMap中&#xff0c;然后Spri…

Cocos Creator3.8 实战问题(三)去除scrollview背景色和label 对齐方式设置无效问题

1、 scrollview 默认背景是白色的&#xff0c; 我们不想要 scrollview 默认的背景颜色&#xff0c;怎么办&#xff1f; 设置 scrollview的color为透明吗&#xff1f; 不对&#xff0c;这会导致 view节点完全透明。 解决方法&#xff1a;直接删除scrollview 的Spritre frame就…