Android 性能优化之启动优化

文章目录

  • Android 性能优化之启动优化
    • 启动状态
      • 冷启动
      • 温启动
      • 热启动
    • 耗时检测
      • 检测手段
      • TraceView
        • 使用方式
        • 缺点
      • Systrace
        • 环境配置
        • 使用方式
        • TraceView和Systrace比较
      • AOP统计耗时
        • 环境配置
        • 使用
    • 优化
      • 白屏优化
      • 异步加载优化
        • 环境配置
        • 使用
      • 延迟加载优化
      • AppStartup
    • 源码下载

Android 性能优化之启动优化

启动状态

在这里插入图片描述

冷启动

冷启动是应用程序启动的默认方式。当用户首次启动应用程序时,或者系统彻底杀死了应用程序进程后再次启动应用程序时,会经历冷启动。在冷启动过程中,系统需要创建一个新的进程,并初始化所有必要的资源。这包括加载应用程序的代码、数据,以及初始化应用程序的环境。冷启动的时间相对较长,因为系统需要执行一系列初始化操作。用户能感受到明显的等待时间,这段时间从点击应用图标到看到应用程序主界面出现。

在冷启动开始时,系统有以下三项任务:

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

系统一创建应用进程,应用进程就负责后续阶段:

  1. 创建应用对象。
  2. 启动主线程。
  3. 创建主 activity。
  4. 膨胀视图。
  5. 创建屏幕布局。
  6. 执行初步绘制。

在这里插入图片描述

温启动

温启动是指应用程序已经在后台运行,但由于系统资源紧张等原因被系统终止。当用户再次启动应用程序时,系统会重新加载应用程序。与冷启动相比,温启动不需要重新创建进程,因此启动时间较短。

热启动

热启动是指应用程序处于前台运行状态,用户通过返回键或应用程序内部的逻辑退到后台,然后又重新显示到前台。在这种情况下,应用程序的进程仍然在运行,所以不需要进行任何初始化操作。热启动是最快的启动方式,因为系统只需要恢复应用程序的前台状态。

耗时检测

检测手段

  • TraceView
  • Systrace
  • AOP统计耗时

TraceView

TraceView 是 Android SDK 中提供的性能分析工具,它可以帮助开发者分析应用程序的方法调用和线程活动。TraceView 专注于应用程序的内部行为,提供了方法执行时间、调用次数、CPU 使用率等详细信息。它通常用于分析应用程序的特定部分或特定场景。

使用方式
public class BaseApp extends Application {  @Overridepublic void onCreate() {super.onCreate();// TraceView开始Debug.startMethodTracing("myTrace001");initRefresh();initTitleBar();initToast();initActivites();// TraceView结束Debug.stopMethodTracing();}
}

运行程序后生成文件:/sdcard/Android/data/com.example.android_performance_optimization/files/myTrace001.trace

在这里插入图片描述

将 trace 文件到处,用 AndroidStudio的 Profiler 工具打开,可以清楚看到各个方法的执行时间:

在这里插入图片描述

缺点
  • 运行时开销严重,整体会变慢。
  • 可能带偏优化方向。

Systrace

Systrace 是 Android SDK 中提供的另一个性能分析工具,它提供了系统级别的跟踪信息,包括内核调度、硬件I/O、进程/线程调度等。Systrace 专注于整个 Android 系统的行为,帮助开发者了解系统资源的使用情况和潜在的瓶颈。

环境配置

https://blog.csdn.net/Donald_Zhuang/article/details/118771191

https://blog.csdn.net/jdsjlzx/article/details/134179374

使用方式
public class BaseApp extends Application {@Overridepublic void onCreate() {super.onCreate();// Systrace开始Trace.beginSection("myTrace002");initRefresh();initTitleBar();initToast();initActivites();// Systrace结束Trace.endSection();}
}

先执行命令:python D:\dev\AndroidSDK\platform-tools\systrace\systrace.py -t 10 -o mytrace.html -a com.example.android_performance_optimization sched freq idle am wm gfx view binder_driver hal dalvik camera input res

然后运行程序,大概10秒后会生成 mytrace.html 文件。

打开 html 文件过滤相关信息后可以看到 Wall Duration 耗时:

在这里插入图片描述

TraceView和Systrace比较

性能消耗

  • TraceView:由于它收集所有方法的耗时信息和嵌套关系,因此本身的性能消耗很大,可能会影响到实际的运行环境,统计的耗时可能不准确。
  • Systrace:采用了不同的思路,通过有限的Label先粗略统计出一个阶段的耗时,定位到问题后再进一步细化和测算分析。这种方式相对于TraceView来说,对性能的影响较小。

适用范围

  • TraceView:更适用于从软件跟踪的角度分析应用程序的性能。
  • Systrace:则更侧重于从系统整体的角度分析Android系统的性能,包括各个关键子系统和服务的运行情况。

AOP统计耗时

环境配置

这里使用第三方框架:https://github.com/FlyJingFish/AndroidAOP

添加依赖库:

implementation 'io.github.FlyJingFish.AndroidAop:android-aop-core:1.8.8'
implementation 'io.github.FlyJingFish.AndroidAop:android-aop-annotation:1.8.8'
annotationProcessor 'io.github.FlyJingFish.AndroidAop:android-aop-processor:1.8.8'
使用

定义注解:

@AndroidAopPointCut(CostTimePointcut.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CostTime {
}

定义切面类:

public class CostTimePointcut implements BasePointCut<CostTime> {@Nullable@Overridepublic Object invoke(@NonNull ProceedJoinPoint proceedJoinPoint, @NonNull CostTime costTime) {long startTime = System.currentTimeMillis();proceedJoinPoint.proceed(); // 继续执行原方法long time = System.currentTimeMillis() - startTime;Class<?> targetClass = proceedJoinPoint.getTargetClass();String className = targetClass.getName();AopMethod targetMethod = proceedJoinPoint.getTargetMethod();String methodName = targetMethod.getName();String builder = className + "#" + methodName + " [" + time + "ms" + "] ";Log.e("CostTime", builder);return null;}
}

使用AOP:

public class BaseApp extends Application {@CostTime@Overridepublic void onCreate() {super.onCreate(); initRefresh(); initTitleBar(); initToast(); initActivites(); }@CostTimeprivate void initActivites() {ActivityManager.getInstance().init(instance);}@CostTimeprivate void initToast() {ToastUtils.init(instance, new ToastStyle());ToastUtils.setDebugMode(AppConfig.isDebug());ToastUtils.setInterceptor(new ToastLogInterceptor());}@CostTimeprivate void initTitleBar() {TitleBar.setDefaultStyle(new TitleBarStyle());}@CostTimeprivate void initRefresh() {SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {@Overridepublic RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {layout.setPrimaryColorsId(R.color.black, android.R.color.white);//全局设置主题颜色return new ClassicsHeader(context);}});SmartRefreshLayout.setDefaultRefreshFooterCreator(new DefaultRefreshFooterCreator() {@Overridepublic RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) {return new ClassicsFooter(context).setDrawableSize(20);}});}
}

输出:

com.example.android_performance_optimization.BaseApp#initRefresh [1ms] 
com.example.android_performance_optimization.BaseApp#initTitleBar [0ms] 
com.example.android_performance_optimization.BaseApp#initToast [0ms] 
com.example.android_performance_optimization.BaseApp#initActivites [1ms] 
com.example.android_performance_optimization.BaseApp#onCreate [2ms] 

优化

  • 白屏优化
  • 异步加载优化
  • 延迟加载优化

白屏优化

在启动时提供一个简洁的初始界面给用户,增强用户体验。

定义主题:

<style name="SplashTheme" parent="AppTheme"><!--        设置背景图--><item name="android:windowBackground">@drawable/shape_splash</item><!--        取消标题栏--><item name="windowNoTitle">true</item><item name="windowActionBar">false</item><!--        设置window不透明--><item name="android:windowIsTranslucent">false</item><!--        禁用窗口的预览动画--><item name="android:windowDisablePreview">true</item><!--        取消遮盖--><item name="android:windowContentOverlay">@null</item><!--        全屏--><item name="android:windowFullscreen">true</item>
</style>

配置AndroidManifest.xml:

<activityandroid:name=".SplashActivity"android:exported="true"android:launchMode="singleTop"android:theme="@style/SplashTheme"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>
</activity>

异步加载优化

环境配置

这里使用第三方框架:https://github.com/aiceking/AppStartFaster

添加依赖库:

implementation 'com.github.aiceking:AppStartFaster:2.2.0'
使用
public class BaseApp extends Application {private static BaseApp instance;public static BaseApp getInstance() {return instance;}@CostTime@Overridepublic void onCreate() {super.onCreate();instance = this; AppStartTaskDispatcher.create().setShowLog(true).addAppStartTask(new ActivityTask(instance)).addAppStartTask(new ToastTask(instance)).addAppStartTask(new TitleBarTask()).addAppStartTask(new RefreshTask()).start().await();}
}

延迟加载优化

IdleHandler 是一个用于在主线程(UI 线程)空闲时执行任务的接口。

使用场景:

  • 数据预加载。
  • 清理资源。
  • 日志上传。
  • 检查更新。
  • 性能分析。

使用:

首先,你需要创建一个实现了IdleHandler接口的类或使用匿名内部类。在queueIdle()方法中定义你希望在空闲时执行的代码逻辑。该方法的返回值决定了IdleHandler的生命周期:

  • 返回true表示IdleHandler将继续保留在集合中,下次消息队列空闲时还会再次调用queueIdle()
  • 返回false表示执行完毕后将从集合中移除,不再重复调用。

定义延迟加载启动器:

public class DelayInitDispatcher {private DelayInitDispatcher() {}public static DelayInitDispatcher newInstance() {return new DelayInitDispatcher();}private LinkedList<Task> mDelayTasks = new LinkedList<>();private MessageQueue.IdleHandler mIdleHandler = new MessageQueue.IdleHandler() {@Overridepublic boolean queueIdle() {if (mDelayTasks.size() > 0) {Task task = mDelayTasks.poll();task.run();}return !mDelayTasks.isEmpty();}};public DelayInitDispatcher addTask(Task task) {mDelayTasks.add(task);return this;}public void start() {Looper.myQueue().addIdleHandler(mIdleHandler);}
}

定义Task接口:

public interface Task extends Runnable{
}

定义2个任务:

public class PreloadTask implements Task {@Overridepublic void run() {try {Thread.sleep(1000L);Log.e("TAG", "预加载数据");} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
public class ClearTask implements Task {@Overridepublic void run() {try {Thread.sleep(2000L);Log.e("TAG", "清理资源");} catch (InterruptedException e) {throw new RuntimeException(e);}}
}

使用:

DelayInitDispatcher.newInstance().addTask(new PreloadTask()).addTask(new ClearTask()).start();

AppStartup

  • AppStartup 是一个可以用于加速App启动速度的 Jetpack 组件。
  • AppStartup 是借助 ContentProvider 进行提前初始化操作

https://blog.csdn.net/qq_14876133/article/details/119247723

源码下载

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

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

相关文章

Reid系列论文学习——无人机场景下基于 Transformer 的轻量化行人重识别

今天介绍的一篇论文是针对无人机场景下的行人重识别&#xff0c;论文题目为&#xff1a;"无人机场景下基于 Transformer 的轻量化行人重识别"。该论文针对无人机场景下行人呈现多角度多尺度的特点、以及传统CNN网络在行人重识别任务中受限于感受野和下采样导致的无法…

关于汽车软件测试的几点想法

如果你有过汽车行业的从业经验&#xff0c;你就应该知道&#xff0c;过去汽车行业只做测试&#xff0c;而不做开发。汽车制造商的主要任务&#xff08;从工程角度看&#xff09;是将来自数百家供应商的数千个零部件组装在一起。考虑到现代软件的复杂性和客户的“挑剔”&#xf…

Rufus 制作启动盘 | 便携的工作空间

唠唠闲话 最近服务器硬盘故障多&#xff0c;在修复过程中&#xff0c;学习了一些操作&#xff0c;这里做个记录。本期主要介绍 U盘启动盘的制作&#xff0c;以及持久化存储。 U 盘启动盘 镜像选择 Ubuntu 的版本命名遵循 “Adjective Animal” 的模式&#xff0c;即 “形容…

新港海岸NCS8822 低功耗DP转VGA 分辨率支持1920*1200*60HZ

NCS8822描述&#xff1a; NCS8822是一个低功耗显示端口到vga转换器。NCS8822集成了一个与DP1.2兼容的接收器和一个高速三通道视频DAC。对于DP1.2输入&#xff0c;NCS8822支持1车道/2车道&#xff0c;也支持车道交换功能。对于VGA输出NCS8822&#xff0c;在60Hz帧率下对WUXGA&a…

C++ 栈-队列-优先级队列

目录 1 栈 2 队列 3 deque 介绍 4 优先级队列 5 反向迭代器 栈也是我们在C语言就模拟实现过的一种数据结构&#xff0c;在C中&#xff0c;栈其实和我们前面模拟实现过的string、vector等容器有一点区别&#xff0c;站起是不是容器&#xff0c;而是一种容器适配器&#xff0c;我…

k8s record 20240705

k8s 安全管理 request 是1g&#xff0c;你得不到要求&#xff0c;我就不创建了&#xff0c;这就是准入控制二次校验 SA就是serviceAccount。 内部是SA和 token, 外部用户进来就是 .kube/config文件 namespace下的是role&#xff0c;整个集群是 ClusterRole. 动作就是Binding li…

pytest-rerunfailures:优化测试稳定性的失败重试工具

笔者在执行自动化测试用例时&#xff0c;会发现有时候用例失败并非代码问题&#xff0c;而是由于服务正在发版&#xff0c;导致请求失败&#xff0c;从而降低了自动化用例的稳定性&#xff0c;最后还要花时间定位到底是自身case的原因还是业务逻辑问题&#xff0c;还是其他原因…

适合家居建材企业的CRM系统盘点(2024版)

当前&#xff0c;CRM市场上&#xff0c;国际巨头的市场优势正在逐渐减弱&#xff0c;国内CRM企业奋起追赶&#xff0c;呈现出强劲的崛起势头。因此&#xff0c;对于家居建材企业来讲&#xff0c;在进行CRM选型时&#xff0c;如何选择一款合适的系统是关乎企业高效发展的重要课题…

矩阵键盘与密码锁

目录 1.矩阵键盘介绍​编辑 2.扫描的概念 3.代码演示&#xff08;读取矩阵键盘键码&#xff09; 4.矩阵键盘密码锁 1.矩阵键盘介绍 为了减少I/O口的占用&#xff0c;通常将按键排列成矩阵形式&#xff0c;采用逐行或逐列的 “扫描”&#xff0c;就可以读出任何位置按键的状态…

免杀笔记 ----> ShellCode Loader !!!

学了那么久的前置知识&#xff0c;终于到了能上线的地方了&#xff01;&#xff01;&#xff01; 不过这里还没到免杀的部分&#xff0c;距离bypass一众的杀毒软件还有很长的路要走&#xff01;&#xff01; 目录 1.ShellCode 2.ShellCode Loader的概念 3.可读可写可…

字符串函数5-9题(30 天 Pandas 挑战)

字符串函数 1. 相关知识点1.5 字符串的长度条件判断1.6 apply映射操作1.7 python大小写转换1.8 正则表达式匹配2.9 包含字符串查询 2. 题目2.5 无效的推文2.6 计算特殊奖金2.7 修复表中的名字2.8 查找拥有有效邮箱的用户2.9 患某种疾病的患者 1. 相关知识点 1.5 字符串的长度条…

代码随想录算法训练营第四十四天|188.买卖股票的最佳时机IV、309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费

188.买卖股票的最佳时机IV 题目链接&#xff1a;188.买卖股票的最佳时机IV 文档讲解&#xff1a;代码随想录 状态&#xff1a;不会 思路&#xff1a; 在股票买卖1使用一维dp的基础上&#xff0c;升级成二维的即可。 定义dp[k1][2]&#xff0c;其中 dp[j][0] 表示第j次交易后持…

虚拟ECU:纯电动汽车发展下的新选择

人类文明的进步是一个不断自我否定、自我超越的过程。21世纪以来&#xff0c;随着科技进步和经济社会发展&#xff0c;能源和交通系统已从独立于自然环境的孤立系统&#xff0c;转变为与自然、技术、社会深度耦合的复杂系统。为实现可持续发展和应对气候变化&#xff0c;世界各…

【C++航海王:追寻罗杰的编程之路】关联式容器的底层结构——AVL树

目录 1 -> 底层结构 2 -> AVL树 2.1 -> AVL树的概念 2.2 -> AVL树节点的定义 2.3 -> AVL树的插入 2.4 -> AVL树的旋转 2.5 -> AVL树的验证 2.6 -> AVL树的性能 1 -> 底层结构 在上文中对对map/multimap/set/multiset进行了简单的介绍&…

《简历宝典》02 - 如果你是HR,你会优先打开哪份简历?

现在的求职环境不必多说&#xff0c;其实我们大家都还是很清楚的。所以&#xff0c;在这个环境下&#xff0c;写一份优秀的简历&#xff0c;目的与作用也不必多说。那么&#xff0c;这一小节呢&#xff0c;我们先从简历这份文档的文档名开始说起。 目录 1 你觉得HR们刷简历的时…

【深度学习】图形模型基础(5):线性回归模型第二部分:单变量线性回归模型

1.引言 在统计学与机器学习的广阔领域中&#xff0c;线性回归作为一种基础而强大的预测技术&#xff0c;其核心在于通过输入变量&#xff08;或称预测器、自变量&#xff09;来估计输出变量&#xff08;响应变量、因变量&#xff09;的连续值。本章聚焦于线性回归的一个基本但…

【C++】相机标定源码笔记- 立体视觉相机的校准和图像矫正类

类主要用于双目相机的标定和矫正。它包含了读取和保存相机模型、计算标定参数以及矫正图像的功能。通过这些功能&#xff0c;可以实现双目相机的标定和矫正&#xff0c;从而提高双目相机的精度和稳定性。 公有函数&#xff1a; 构造函数、带参构造函数、析构函数、读取双目相机…

摩斯邀您参加“WAIC 2024世界人工智能大会”

2024世界人工智能大会暨人工智能全球治理高级别会议&#xff08;简称“WAIC 2024”&#xff09;将于7月在上海世博中心、世博展览馆举行&#xff0c;论坛时间为7月4日-6日&#xff0c;展览时间为7月5日-7日。大会展览面积超5.2万平方米&#xff0c;重点围绕核心技术、智能终端、…

STM32要学到什么程度才算合格?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; STM32 这玩意儿要学到啥…

vscode 前行复制到下一行

目录 这个技巧也比较多 选择 python解释器 F1 Ctrl Shift P 跳转上一次编辑 下一次编辑 Ctrl d 会把当前行复制到下一行 步骤1&#xff1a;打开键绑定设置 使用VS Code设置换行 这个技巧也比较多 VS Code技巧汇总_vs code反缩进-CSDN博客 选择 python解释器 F1 Ctrl Shi…