一文高端Android性能优化-总结篇

news2024/11/27 3:31:39

以下从几个方面来总结一下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(){
        @Override
        publicvoid 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:第三方工具的懒加载初始化,即用到的时候再进行初始化

更多性能优化知识点:点击这里

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

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

相关文章

OIDC OAuth2.0 协议及其授权模式详解|认证协议最佳实践系列【1】

OIDC / OAuth2.0 是一种开放的标准&#xff0c;可以帮助应用程序安全地访问用户的资源&#xff0c;而无需将用户的凭据&#xff08;如用户名和密码&#xff09;暴露给应用程序&#xff0c;我们可以通过标准协议&#xff0c;建立集中的用户目录和统一认证中心&#xff0c;将内外…

健身的时候可以戴耳机吗、最适合健身时佩戴的耳机推荐

戴着耳机锻炼&#xff0c;听着动感的音乐&#xff0c;会让你心潮澎湃&#xff0c;瞬间感觉自己力大无穷。那什么样的耳机更适合在健身房锻炼时戴呢&#xff1f;首先稳固性和舒适度一定要比较好&#xff0c;毕竟在运动的过程中老是感觉到不适或者掉落&#xff0c;那真的是很令人…

计算机组成原理:3. 系统总线

更好的阅读体验\huge{\color{red}{更好的阅读体验}}更好的阅读体验 文章目录3.1 总线的基本概念3.1.1 总线的定义3.1.2 总线的分类片内总线系统总线通信总线3.2 总线特性及性能指标3.2.1 总线特性3.2.2 总线性能指标3.2.3 总线标准3.3 总线结构3.3.1 单总线结构3.3.2 多总线结构…

AD域备份和恢复工具

Microsoft的本地Active Directory备份和恢复功能不适用于对象级备份和属性级还原。使用RecoveryManager Plus&#xff0c;您不仅可以备份和还原所有AD对象&#xff0c;还可以备份和还原其他基本AD元素&#xff0c;例如架构属性&#xff0c;组成员身份信息和Exchange属性。此外&…

字符串中<br>处理

需求&#xff1a; 后端返回的字符串中带有br换行符&#xff0c;前端需要处理行内及行尾的换行符。具体需求可分为以下两个&#xff1a; 若是字符串末尾有换行符&#xff0c;需要去掉。若是字符串内有换行符&#xff0c;有两种需求&#xff1a;①将换行符转换成逗号或其它符号&…

年薪30万,我也曾达到人生巅峰,入职字节一个月,却被无情被裁......

今年的金三银四并不像往年那样有铺天盖地的岗位和约不过来的面试机会&#xff0c;再看正在招聘的岗位&#xff0c;动不动就要求代码能力&#xff0c;能开发自动化测试平台&#xff0c;能对已有xxx框架二次开发&#xff0c;还要上机笔试&#xff0c;变态程度不亚于古代皇帝选妃了…

uni-app Some selectors are not allowed in component wxss解决方案

报错信息如下 Some selectors are not allowed in component wxss, including tag name selectors, ID selectors, and attribute selectors. 注意看尾巴&#xff0c; (./uni_modules/uni-load-more/components/uni-load-more/uni-load-more.wxss:65:29) 打开这个组件uni-lo…

工厂在智慧升级过程中,企业需要用到哪些系统呢?

今天我们优先来分析一下流程制造型企业的需求。流程制造行业智能工厂要实现智能化&#xff0c;必须包含生产管理、供应链管理、工艺管理、设备管理、质量管理等全生命周期业务流程&#xff0c;那么这个全生命周期业务流程相对应的平台就会有以下几大平台来分别实现智能化&#…

Linux驱动开发—最详细应用程序调用驱动程序解析

Linux下应用程序调用驱动程序流程 Linux下进行驱动开发,完全将驱动程序与应用程序隔开,中间通过C标准库函数以及系统调用完成驱动层和应用层的数据交换。驱动加载成功以后会在“/dev”目录下生成一个相应的文件,应用程序通过对“/dev/xxx” (xxx 是具体的驱动文件名字) 的文…

深度分析2种最常用待办事项清单法+工具实操

建待办事项清单的方法有很多种&#xff0c;你可能已经熟悉了其中一种&#xff0c;但没有了如指掌&#xff0c;恐怕也没有想过哪种方法最适合自己&#xff0c;给大家整理当下职场最常用的两个代办清单事项方法&#xff0c;只需看这两个就够你用几年了。 一、四象限法 “四象限…

全面分析前端的网络请求方式(对ajax理解的勘误)

文章目录前言AjaxFetchAxios三者关系前言 在掘金看到一篇关于ajax和fetch以及aixos的文章&#xff0c;才发现自己对ajax的理解是错误的&#xff0c;一直以为ajax就是js中xhr对象&#xff0c;把他们两之间画上了等号&#xff0c;殊不知从根本上就理解错了。 这里就不对原生的xh…

疯狂的SOVA:Android银行木马“新标杆”

2021年8月初&#xff0c;一款针对Android银行APP的恶意软件出现在人们的视野中&#xff0c;ThreatFabric 安全研究人员首次发现了这一木马&#xff0c;在其C2服务器的登录面板&#xff0c;研究人员发现&#xff0c;攻击者将其称之为SOVA。 ** SO** ** V** ** A简介** 在俄语中…

Mac Maven环境搭建安装和配置详细步骤

一、Maven简介Maven 是 Apache 软件基金会的一个开源项目,是一个优秀的项目构建工具,它用来帮助开发者管理项目中的 jar,以及 jar 之间的依赖关系、完成项目的编译、测试、打包和发布等工作。二、Mavende优点1、原来的项目中需要的jar包必须手动“复制”、”粘贴” 到WEB-INF/l…

产品经理必懂的技术知识

API 是不是经常听见程序猿小哥哥A说&#xff1a;“这个简单&#xff0c;直接调用现成的接口就可实现。 一会儿程序猿小哥哥B说&#xff1a;“你这个不行&#xff0c;我们的第三方服务接口不支持。” 此时你的心里活动&#xff1a;API ≈ 听不懂 啥子是接口哦&#xff1f;接口…

git合并分支

在复杂系统的开发过程中&#xff0c;我们经常需要通过不同的功能或环境分支来进行管理&#xff0c;那么开发阶段完成时&#xff0c;还需要进行合并&#xff0c;下边分享一下合并的流程&#xff1a;首先确保要合并的两个分支 本地分支与远程分支一致可以通过IDEA切换对应分支拉取…

【已解决】解决IDEA的maven刷新依赖时出现Connot reconnect错误

前言 小编我将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识&#xff0c;有兴趣的小伙伴可以关注一下&#xff01;也许一个人独行&#xff0c;可以走的很快&#xff0c;但是一群人结伴而行&#xff0c;才能走的更远&#xff01;让我们在成长的道路上互相学习&#…

SAP分析云2023年第一季度亮点更新介绍

本文介绍了SAP分析云2023年第1季度的季度发布&#xff08;QRC&#xff09;新功能和增强功能。较于以往的版本&#xff0c;这次的更新在系统管理和服务管理、增强分析、业务内容交付、仪表盘和故事设计、Microsoft集成等方面做了产品的功能更新改进。那就和阿拓一起看看吧&#…

工作中,python真的有用吗?

普通上班族学Python有用吗&#xff1f; 那么&#xff0c;我也在这里提出一个问题&#xff1a;Python究竟适不适合办公人士来学习&#xff0c;以及学了之后究竟能不能给我的工作来带质一般的飞跃&#xff1f; 以我的亲身经历为例&#xff0c;我可以很负责的告诉大家&#xff0c…

Liunx服务器安装SVN

一、下载svn安装包链接&#xff1a;https://pan.baidu.com/s/1gkS0tef2kQP6nvXOS64hUw 提取码&#xff1a;cyuw二、SVN安装部署通过sftp将文件拉取到目的主机路径&#xff1a;/usr/package 跳转文件路径: cd /usr/package 执行解压命令:tar -zxvf subversion-1.14.2.tar.gz 执行…

Mysql的安装、语法、优化

1 数据库 数据库是存储数据&#xff0c;管理数据的仓库。 常见的数据库有两种&#xff1a; 关系型数据库&#xff1a;数据关系紧密。关系模型是二维表格模型&#xff0c;一个关系型数据库就是由二维表及其之间的关系组成的一个数据集合。 Oracle、MySQL、SQLServer、Access…