一文高端Android性能优化-总结篇
以下从几个方面来总结一下Android的性能优化:
1:界面卡顿优化
2:内存优化
3:App启动优化
界面卡顿优化
Android的界面为每秒60帧,即必须在16ms内完成1帧的绘制,如果某个方法耗时过程,导致16ms内无法完成绘制,会导致丢帧,丢帧的多了,直观上感受就是界面卡顿。
60帧是人眼观看动画比较合适的频率,如果每秒的帧数过少,即频繁的出现丢帧,就会感觉界面的卡顿。
1:通过Traceview找出卡主主线程的地方
卡住主线程说明函数在主线程被调用的时长比较长,包括:
1)单个函数调用的时长长
2)函数被调用的次数比较多
2:使用方法:
1)Terminal打开DDMS,输入指令:Monitor
2)点击start method profiling

3)操作APP可能有问题的界面
4)再次点击stop method profiling,生成表格:

3:具体案例分析:recyclerView的onBindViewHolder,当复用屏幕外的数据是,是脏数据,会进行重新绑定,调用onBindViewHolder

@Override
publicvoid onBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
Log.d(TAG, "onBindViewHolder--->" + position);
。。。。。。
。。。。。。。
SystemClock.sleep(7);
}

SystemClock.sleep(10)模拟RecyclerView滚动过程中的耗时操作,操作Recyclerview,得到以下表格:
Real Time/Call表示一个函数被调用的时长, Calls+Recursion + call totals表示一个函数被调用和被递归调用的次数

内存优化:
1:Memory Monitor:
Memory Monitor只能看个大概,可以查看内存抖动,或者内存增长的趋势,具体的小的泄漏,还得通过Heap Viewer查看
内存抖动:短时间内发生了多次内存的涨跌,意味着很有可能发生率内存抖动。
内存抖动带来的问题:短时间内的内存飙升,系统需要频繁的进行GC,而GC是需要主线程停下来,并且占用CPU资源的,会导致界面卡顿。
例子1:
publicvoid click(View view) {
for (int i = 0; i < 100; i++) {
byte[] b = newbyte[2000];
}
}
例子2:

privateint nums[][] = newint[250][250];
//内存抖动案例:
//短时间内创建大量的临时变量privatevoid init() {
Random random = new Random();
for (int i = 0; i < nums.length; i++) {
for(int j=0; j<nums[i].length; j++){
nums[i][j] = random.nextInt(1000);
}
}
}
privatevoid printNums(){String totalNums = "";for (int i = 0; i < nums.length; i++) {for(int j=0; j<nums[i].length; j++){totalNums += nums[i][j];}}}
//优化:private void printNums2(){StringBuffer totalNums = new StringBuffer();for (int i = 0; i < nums.length; i++) {for(int j=0; j<nums[i].length; j++){totalNums.append(nums[i][j]);}}}
使用Monitor监控:

避免内存抖动的方法:
1)尽量避免在循环体内创建对象,应该把对象创建移到循环体外
2)自定义view的onDraw会被频繁调用,避免在这个函数里面new一个新的对象
2:Heap Viewer:
监控:能够实时观测内存的变动(短时间内通过Memory Monitor是看不出来的,曲线坡度太小,内存变动值很小,定位不到具体的代码)
Heap Viewer具体定位到哪个位置内存泄漏。
内存泄漏例子:

protectedvoid onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//test1(); init();handler.sendEmptyMessageDelayed(0, 100000);}

//模拟当MainActivity跳转到MainActivity2的时候,// 延迟发送消息导致的内存泄漏问题private Handler handler = new Handler(){@Overridepublicvoid handleMessage(@NonNull Message msg) {super.handleMessage(msg);}};publicvoid click(){Intent intent = new Intent(this, MainActivity2.class);startActivity(intent);finish();}
首先运行应用,处在MainActivity,点击Dump Java Heap,获取当前内存的快照:

得到以下表格:

修改为根据包名查看更方便快速定位到我们自己的代码:

Leaks为0说明当前没有发生内存泄漏
MainActivity的depth为3,说明MainActivity有被引用

点击MainActivity的click,跳转到MainActivity2,MainActivity.finish(),模拟MainActivty发生内存泄漏的场景(Handler引用MainActivity导致内存泄漏),然后点击GC,再截取内存快照
Dump Java Heap:

黄色的Leaks为2说明发生了内存泄漏,点击Leaks,通过以下References可以找到MainActivity被引用的路径。

3:LeakCanary
在一个Activity执行完onDestroy后,将它放入到WeakReference中,然后将这个WeakReference类型的Activity的对象与ReferenceQueue关联,注意: 如果一个对象要被GC回收了,会把它引用的对象放入到ReferenceQueue中。这时候只需要在ReferenceQueue中去查找是否存在该对象,如果没有就执行一个GC,再次查找,如果还是没有,则说明该对象可能无法被回收,也就可能发生了内存泄漏,最后使用HAHA这个开源库取分析dump之后的heap内存
在一个Activity执行完onDestroy后,将它放入到WeakReference中,然后将这个WeakReference类型的Activity的对象与ReferenceQueue关联,注意: 如果一个对象要被GC回收了,会把它引用的对象放入到ReferenceQueue中。这时候只需要在ReferenceQueue中去查找是否存在该对象,如果没有就执行一个GC,再次查找,如果还是没有,则说明该对象可能无法被回收,也就可能发生了内存泄漏,最后使用HAHA这个开源库取分析dump之后的heap内存
在一个Activity执行完onDestroy后,将它放入到WeakReference中,然后将这个WeakReference类型的Activity的对象与ReferenceQueue关联,注意: 如果一个对象要被GC回收了,会把它引用的对象放入到ReferenceQueue中。这时候只需要在ReferenceQueue中去查找是否存在该对象,如果没有就执行一个GC,再次查找,如果还是没有,则说明该对象可能无法被回收,也就可能发生了内存泄漏,最后使用HAHA这个开源库取分析dump之后的heap内存
在一个Activity执行完onDestroy后,将它放入到WeakReference中,然后将这个WeakReference类型的Activity的对象与ReferenceQueue关联,注意: 如果一个对象要被GC回收了,会把它引用的对象放入到ReferenceQueue中。这时候只需要在ReferenceQueue中去查找是否存在该对象,如果没有就执行一个GC,再次查找,如果还是没有,则说明该对象可能无法被回收,也就可能发生了内存泄漏,最后使用HAHA这个开源库取分析dump之后的heap内存
分为两个步骤:
1)通过虚引用的ReferenceQueue,判断一个对象是否被回收:
虚引用:对于对象来说,是无感的,如果只存在虚引用,GC的时候会直接被回收。虚引用的目的是为了追踪一个对象被回收的时机。如果一个定义了虚引用的对象GC之后被回收了,这个对象会被放入RefereceQueue中,LeakCanary就是在GC之后去检测该队列中是否有该对象判断该对象是否已经被回收。
2)初步判定有内存泄漏之后,通过开源库Haha分析dump之后的heap内存,从而定位到具体的内存泄露的对象的引用链条。
APP应用启动优化
1:冷启动和热启动
1)冷启动:app没有启动过或者进程被杀死,系统不存在该app进程,此时启动为冷启动。冷启动流程就是app启动流程全过程,包括创建app进程、加载资源、启动MainThread、初始化SplashActivity并加载布局等。
2)热启动:app暂时退到了后台,热启动将它从后台重新带到前台,展示给客户。
我们要做的优化就是针对热启动
3):冷启动的函数调用过程:
Zygote Fork Proccess
-> Application:attachBaseContext()
-> Application:onCreate()
-> MainActiviity:onCreate()
2:用TraceView获取App的启动耗时,查找具体的耗时的函数进行优化:

publicclass MyApplication extends Application {
@Override
publicvoid onCreate() {
Debug.startMethodTracing("startApp");
super.onCreate();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Debug.stopMethodTracing();
}
}

在/sdcard/目录下得到一个startApp.trace文件

通过DDMS打开该文件:可以看到Application里面的onCreate里的哪些代码进行了耗时操作:

3:解决方案:
1)将启动页主题背景设置成闪屏页图片
这么做的目的主要是为了消除启动时的黑白屏,给用户一种秒响应的感觉,但是并不会真正减少用户启动时间,仅属于视觉优化。
2)第三方工具的初始化一般都在Application的onCreate里面执行,会造成大量的耗时,解决方案:
a:放在子线程中加载不影响业务的情况,则优先选择放在子线程中加载
b:第三方工具的懒加载初始化,即用到的时候再进行初始化
更多性能优化知识点:点击这里

相关文章:

一文高端Android性能优化-总结篇
以下从几个方面来总结一下Android的性能优化:1:界面卡顿优化2:内存优化3:App启动优化界面卡顿优化Android的界面为每秒60帧,即必须在16ms内完成1帧的绘制,如果某个方法耗时过程,导致16ms内无法完…...

深入讲解CFS组调度!(上)
注:本文缩写说明 一、CFS组调度简介 1.1. 存在的原因 总结来说是希望不同分组的任务在高负载下能分配可控比例的CPU资源。为什么会有这个需求呢,比如多用户计算机系统每个用户的所有任务划分到一个分组中,A用户90个相同任务,而B…...

大数据实操项目分享:餐饮智能推荐服务在线实习项目
项目背景:在“互联网"背景下,餐饮企业的经营方式发生了很大的变革:团购和020拓宽了销售 渠道,电子点餐、店内WIFI等信息技术提升了服务水平,大数据、私人定制更好地满足了细分市场的需求等。但是与此同时…...
代码随想录day38
动态规划五部曲 确定dp数组以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 509. 斐波那契数 https://leetcode.cn/problems/fibonacci-number/ class Solution {public int fib(int n) {if(n0) return 0;if(n<3) return 1;int[] dp new int[n]…...

《计算机网络:自顶向下方法》实验5:TCP
Q1 包含HTTP POST消息的TCP报文段的序号是多少?注意:为了发现POST 命令, 你需要在wireshark底部的报文内容域窗口中去查找,查找数据中包含 “POST”的段。 如图所示,由报文中的POST 和 HTTP/1.1可知,其包含HTTP POST消息; TCP报文段的序号可见TCP报文: Sequence Number:…...

【踩坑指南】Stable Diffusion 服务器端部署笔记
文章目录下载github文件配置环境ckpt文件权重下载生成图像NSFW检查(瑟图过滤)下载github文件 https://github.com/CompVis/stable-diffusion 这个网址,下载压缩包解压,也可以用git clone下载 配置环境 这一步坑最多,…...

[qiankun]-多页签缓存
[qiankun]-多页签缓存环境功能需求多页签缓存方案方案1.主服务进行html替换方案2.微服务vnode 替换方案3.每个微服务都不卸载微服务加载方式的选择微服务的路由路径选择微服务的缓存工具微服务的容器使用tab作为微服务的挂载容器使用微服务路由作为微服务的挂载容器场景描述微服…...

2|电子技术|数字电子技术基础|雨课堂习题|考前回顾
A/DD/A转化横向与阵列 相乘,竖向为或阵列 相加!功率放大电路克服交越失真,是在乙类的基础上增加两个二极管,使微导通,使三极管导通时间大于半个周期,小于一个周期,构成甲乙类工作状态。选择填空…...

vue+echarts:圆形柱状图设置角度和最大值
第020个点击查看专栏目录本示例是显示圆形的柱状图,angleAxis设置一个max, angleAxis上startAngle:90 , 将0点设置为最顶点。 文章目录示例效果示例源代码(共100行)相关资料参考专栏介绍示例效果 示例源代码…...

Linux系统安装Nginx常见报错问题
安装Nginx从nginx官网下载所需版本的nginx,http://nginx.org/下载之后,将安装包上传到linux系统指定路径解压文件,tar -zxvf nginx-1.22.1.tar.gz (此处用1.22.1版本为例)进入安装包目录,cd nginx-1.22.1执…...
按下按键之后,打印一句话------>三个按键需要实现
main.c: #include "key.h" extern void printf(const char *fmt, ...); void delay_ms(int ms){ int i,j; for(i 0; i < ms;i) for (j 0; j < 1800; j);} int main(){ //key1键盘 //EXIT控制器初始化 void PF9_exti_init(); //GICD控…...
Mac配置VScode
Mac配置VScode 常用技巧 命令调色板 根据您当前的上下文访问所有可用的命令。 键盘快捷键:⇧⌘P 快速打开 快速打开文件。 键盘快捷键:⌘P **提示:**类型?查看命令建议。 在最近打开的文件夹和工作区之间导航 最近打开 键盘快捷…...

MAC地址IP地址 端口
网络结构: 服务器-客户机(C/S)Client-Server结构,如QQ,LOL都拥有客户端 优点:响应速度快,形式多样,安全新较高缺点:安装软件和维护,不能跨平台LINUX/windows/MAC浏览器-…...

关于虚拟数字人你想知道的都在这里
2022年底,微软旗下的人工智能实验室Open AI发布的对话式大型语言模型ChatGPT聊天机器人一夜蹿红,5天用户量超百万,在各大中外媒体平台掀起了一阵热潮。也带火了人工智能相关产业,AI虚拟数字人就是其中之一,一个随着元宇…...

分布式任务调度处理方案(无代码)
业务涉及到,需要向数据库、redis、elasticsearch、MinIO写四份数据,这里存在分布式事务问题。如何解决问题,先分析cap,是要保证可用性,还是保证一致性。如何选择是CP还是AP?分析业务场景CP的场景࿱…...

2023年博管办香江学者计划、澳门青年学者开始申报
2023年2月20日,全国博士后管委会办公室官方网站发出了2023年香江学者计划、澳门青年学者计划和博士后国(境)外学术交流项目申报指南,以下知识人网小编仅转载香江学者计划和澳门青年学者计划申报指南并做重点解读。知识人网整理香江…...

(二十一)、实现评论功能(1)【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】
1,评论回复模块的样式布局 1.1 在detail页面添加uview中的 Empty 内容为空组件 <!-- 评论区 --><view class"comment"><u-empty mode"comment" icon"http://cdn.uviewui.com/uview/empty/comment.png"></u-emp…...

【Docker】初识Dcoker以及镜像操作(一)
目录 1.初识Docker 1.1.什么是Docker 1.1.1.应用部署的环境问题 1.1.2.Docker解决依赖兼容问题 1.1.3.Docker解决操作系统环境差异 1.1.4.小结 1.2.Docker和虚拟机的区别 1.3.Docker架构 1.3.1.镜像和容器 1.3.2.DockerHub 1.3.3.Docker架构 1.3.4.小结 1.4.安装D…...
(1)C#传智:在vs2022中基本了解(第一天)
开始vs2022中C#入门,就是一笔记,算不上原创,没办法得选啊。 一、vs中卸载项目和移除项目有什么区别? 1、卸载、移除都不会移除物理文件,只会删除关联 2、卸载删除关联的程度低,卸载后项目只是“变灰色…...

【数据结构与算法】算法的时间复杂度和空间复杂度
文章目录前言1.算法效率1.1.如何衡量一个算法的好坏1.2.算法的复杂度2.时间复杂度2.1.时间复杂度的概念2.2.大O的渐进表示法2.3.常见时间复杂度计算举例2.4.常见时间复杂度3.空间复杂度4.复杂度oj练习Practice.1 消失的数字Practice.2 旋转数组写在最后前言 关于时空复杂度的分…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...