Android 客户端性能优化(魅族资深工程师毫无保留奉献)

拯救者R7000P(2021)装双系统Ubuntu20.04 解决联发科MT7921无线网卡在Ubuntu中不能联网 拯救者R7000P(2021)装双系统Ubuntu20.04/Ubuntu18.04 电脑配置:联想拯救者R7000P CPU:AMD R7-5800H GPU:RTX3060-6G 内存:16GB 固态:500G(原装)+500(加装) 1.做系统盘(本文以Ubuntu20.04为例) 1.下载Ubuntu20.04镜像 直接去Ubuntu官网或者一些国内的镜像去下载都可以,这里给出一个网址https://ubuntu.com/download/desktop,根据需要下载自己学要的Ubuntu版本,后缀 阅读详情

本文由魅族科技有限公司资深Android开发工程师degao(嵌入式企鹅圈原创团队成员)撰写,是degao在嵌入式企鹅圈发表的第一篇原创文章,毫无保留地总结分享其在领导魅族多个项目开发中的Android客户端性能优化经验,极具实践价值!

众所周知,一个好的产品,除了功能强大,好的性能也必不可少。有调查显示,近90%的受访者会因为APP性能差而卸载,性能也是造成APP用户沮丧的头号原因。

那Android客户端性能的指标都有哪些?如何发现和定位客户端的性能问题?本文结合多个项目的开发实践,给出了要关注的重要指标项目,以及定位和解决性能问题的一般步骤。

性能优化应该贯穿于功能开发的全部周期,而不是做完一次后面便不再关注。每次发布版本前,最好能对照标准检查下性能是否达标。

记住:产品=性能×功能!

更多性能优化资料以及Android面试题资料和Android进阶资料请点击:GitHub

一、 性能检查项

1. 启动速度

1)这里的启动速度指的是冷启动的速度,即杀掉应用后重新启动的速度,此项主要是和你的竞品对比。

2)不应在Application以及Activity的生命周期回调中做任何费时操作,具体指标大概是你在onCreate,onResume,onStart等回调中所花费的总时间最好不要超过400ms,否则用户在桌面点击你的应用图标后,将感觉到明显的卡顿。

2. 界面切换

1)应用操作时,界面和动画不应有明显卡顿;

2)可通过在手机上打开 设置开发者选项调试GPU过度绘制,然后操作应用查看gpu是否超线进行初步判断;

3. 内存泄露

1)back退出不应存在内存泄露,简单的检查办法是在退出应用后,用命令adb shell dumpsys meminfo 应用包名查看 Activities Views 是否为零;

2)多次进入退出后的占用内存TOTAL不应变化太大;

4. onTrimMemory回调

1)应用响应此回调释放非必须内存;

2)验证可通过命令adb shell dumpsys gfxinfo 应用包名-cmd trim 5后,再)用命令adb shell dumpsys meminfo 应用包名查看内存大小。

5. 过度绘制

打开设置中的GPU过度绘制开关,各界面过度绘制不应超过2.5x;也就是打开此调试开关后,界面整体呈现浅色,特别复杂的界面,红色区域也不应该超过全屏幕的四分之一;

6. lint检查

1)通过Android Studio中的 AnalyzeInspect Code 对工程代码做静态扫描;找出潜在的问题代码并修改;

2) 0 error & 0 warning,如果确实不能解决,需给出原因。

7. 反射优化

1)在代码中减少反射调用;

2)对频繁调用的返回值进行Cache;

8. 稳定性

1)连续48小时monkey不应出现闪退,anr问题。

2)如果应用接入了数据埋点的sdk,比如百度统计sdk等,这些sdk都会将应用的崩溃信息上报回来,开发者应每天关注这些统计到的崩溃日志,严格控制应用的崩溃率;

9. 耗电

1)应用进入后台后不应异常消耗电量;

2)操作应用后,退出应用,让应用处于后台,一段时间后通过adb shell dumpsys batterystats查看电量消耗日志看是否存在异常。

二、性能问题常见原因

性能问题一般归结为三类:

1. UI卡顿和稳定性:这类问题用户可直接感知,最为重要;

2. 内存问题:内存问题主要表现为内存泄露,或者内存使用不当导致的内存抖动。如果存在内存泄露,应用会不断消耗内存,易导致频繁gc使系统出现卡顿,或者出现OOM报错;内存抖动也会导致UI卡顿。

3. 耗电问题:会影响续航,表现为不必要的自启动,不恰当持锁导致系统无法正常休眠,系统休眠后频繁唤醒系统等;

三、UI卡顿常见原因和分析方法

下面分别介绍出现这些问题的常见原因以及分析这些问题的一般步骤。

1.卡顿常见原因

1)人为在UI线程中做轻微耗时操作,导致UI线程卡顿;

2) 布局Layout过于复杂,无法在16ms内完成渲染;

3)同一时间动画执行的次数过多,导致CPU或GPU负载过重;

4) View过度绘制,导致某些像素在同一帧时间内被绘制多次,从而使CPU或GPU负载过重;

5) View频繁的触发measure、layout,导致measure、layout累计耗时过多及整个View频繁的重新渲染;

6) 内存频繁触发GC过多(同一帧中频繁创建内存),导致暂时阻塞渲染操作;

7) 冗余资源及逻辑等导致加载和执行缓慢;

8)工作线程优先级未设置为

Process.THREAD_PRIORITY_BACKGROUND

导致后台线程抢占UI线程cpu时间片,阻塞渲染操作;

9) ANR;

2. 卡顿分析解决的一般步骤

1)解决过度绘制问题

在设置开发者选项调试GPU过度绘制中打开调试,看对应界面是否有过度绘制,如果有先解决掉:

定位过渡绘制区域

利用Android提供的工具进行位置确认以及修改(HierarchyView , Tracer for OpenGL ES)

定位到具体的视图(xml文件或者View)

通过代码和xml文件分析过渡绘制的原因

结合具体情况进行优化

使用Lint工具进一步优化

  1. 检查是否有主线程做了耗时操作:

严苛模式(StrictMode),是Android提供的一种运行时检测机制,用于检测代码运行时的一些不规范的操作,最常见的场景是用于发现主线程的IO操作。应用程序可以利用StrictMode尽可能的发现一些编码的疏漏。

开启 StrictMode

对于应用程序而言,Android 提供了一个最佳使用实践:尽可能早的在

android.app.Application 或 android.app.Activity 的生命周期使能 StrictMode,onCreate()方法就是一个最佳的时机,越早开启就能在更多的代码执行路径上发现违规操作。

监控代码

publicvoidonCreate(){
if(DEVELOPER_MODE){
StrictMode.setThreadPolicy(newStrictMode.ThreadPolicy.Builder()
.detectAll().penaltyLog().build());
StrictMode.setVmPolicy(newStrictMode.VmPolicy.Builder()
.detectAll().penaltyLog().build());
}
super.onCreate();
}

如果主线程有网络或磁盘读写等操作,在logcat中会有"D/StrictMode"tag的日志输出,从而定位到耗时操作的代码。

3)如果主线程无耗时操作,还存在卡顿,有很大可能是必须在UI线程操作的一些逻辑有问题,比如控件measure、layout耗时过多等,此时可通过Traceview以及systrace来进行分析。

4)Traceview:Traceview主要用做热点分析,找出最需要优化的点。

打开DDMS然后选择一个进程,接着点击上面的“Start Method Profiling”按钮(红色小点变为黑色即开始运行),然后操作我们的卡顿UI,然后点击"Stop Method Profiling",会打开如下界面:

图中展示了Trace期间各方法调用关系,调用次数以及耗时比例。通过分析可以找出可疑的耗时函数并进行优化;

5)systrace:抓取trace:

执行如下命令:

$cdandroid-sdk/platform-tools/systrace
$pythonsystrace.py--time=10-omynewtrace.htmlschedgfxviewwm复制代码

操作APP,然后会生成一个mynewtrace.html 文件,用Chrome打开。

图示如下:

通过分析上面的图,可以找出明显存在的layout,measure,draw的超时问题。

6)导入如下插件,可通过在方法上添加@DebugLog来打印方法的耗时:

 

build.gradle:
buildscript{
dependencies{

//用于方便调试性能问题的打印插件。给访法加上@DebugLog,就能输出该方法的调用参数,以及执行时间;

 

classpathcom.jakewharton.hugo:hugo-plugin:1.2.1
}
}

//用于方便调试性能问题的打印插件。给访法加上@DebugLog,就能输出该方法的调用参数,以及执行时间;

 

applyplugin:com.jakewharton.hugo
java:
@DebugLog
publicvoidtest(inta){
intb=a*a;
}

四、内存性能分析优化

1.内存泄露

该问题目前在项目中一般用leakcanary基本就能搞定,配置起来也相当简单:

 

build.gradle:
dependencies{
debugCompilecom.squareup.leakcanary:leakcanary-android:1.3.1//or1.4-beta1
releaseCompilecom.squareup.leakcanary:leakcanary-android-no-op:1.3.1//or1.4-beta1
testCompilecom.squareup.leakcanary:leakcanary-android-no-op:1.3.1//or1.4-beta1
}

 

java:
publicclassExampleApplicationextendsApplication{

@OverridepublicvoidonCreate(){
super.onCreate();
LeakCanary.install(this);
}
}

一旦有内存泄露,将会在通知栏生成一条通知,点开可看到泄露的对象以及引用路径:

2.内存抖动

如果代码中存在在onDraw或者For循环等多次执行的代码中分配对象的行为,会导致运行过程中gc次数增多,影响ui流畅度。一般这些问题都可通过lint工具检测出来。

五、耗电量优化建议

电量优化主要是注意尽量不要影响手机进入休眠,也就是正确申请和释放WakeLock,另外就是不要频繁唤醒手机,主要就是正确使用Alarm。

六、一些好的代码实践

1. 节制地使用Service

2. 当界面不可见时释放内存

3. 当内存紧张时释放内存

4. 避免在Bitmap上浪费内存

对大图片,先获取图片的大小信息,根据实际需要展示大小计算inSampleSize,最后decode;

publicstaticBitmapdecodeSampledBitmapFromFile(Stringfilename,
intreqWidth,intreqHeight){
//FirstdecodewithinJustDecodeBounds=truetocheckdimensions
finalBitmapFactory.Optionsoptions=newBitmapFactory.Options();
options.inJustDecodeBounds=true;
BitmapFactory.decodeFile(filename,options);
//CalculateinSampleSize
options.inSampleSize=
reqHeight);
calculateInSampleSize(options,
reqWidth,
//DecodebitmapwithinSampleSizeset
options.inJustDecodeBounds=false;
returnBitmapFactory.decodeFile(filename,options);
}
publicstaticintcalculateInSampleSize(BitmapFactory.Optionsoptions,
intreqWidth,intreqHeight){
//Rawheightandwidthofimage
finalintheight=options.outHeight;
finalintwidth=options.outWidth;
intinSampleSize=1;
if(height>reqHeight||width>reqWidth){
if(width>height){
inSampleSize=Math.round((float)height/(float)reqHeight);
}else{
inSampleSize=Math.round((float)width/(float)reqWidth);
}
}
returninSampleSize;
}

5. 使用优化过的数据集合

6. 谨慎使用抽象编程

7. 尽量避免使用依赖注入框架

很多依赖注入框架是基于反射的原理,虽然可以让代码看起来简洁,但是是有碍性能的。

8. 谨慎使用external libraries

9. 优化整体性能

10. 使用ProGuard来剔除不需要的代码

android{
buildTypes{
release{
minifyEnabledtrue
shrinkResourcestrue
proguardFilesgetDefaultProguardFile(proguard-android.txt),src/main/proguard-project.txt
signingConfigsigningConfigs.debug
}
}

11. 慎用异常,异常对性能不利

抛出异常首先要创建一个新的对象。Throwable 接口的构造函数用名为

fillInStackTrace() 的本地方法,fillInStackTrace() 方法检查栈,收集调用跟踪信

息。只要有异常被抛出,VM 就必要调整调用栈,因为在处理过程中创建了一

个新对象。

异常只能用于错误处理,不应该用来控制程序流程。

以下例子不好:

try{
startActivity(intentA);
}catch(){
startActivity(intentB);
}

应该用下面的语句判断:

if(getPackageManager().resolveActivity(intentA,0)!=null)

不要再循环中使用 try/catch 语句,应把其放在最外层,使用 System.arraycopy()代替 for 循环复制。

更多性能优化资料以及Android面试题请点击:GitHub

i.MX6ULL系统移植 | 使用busybox制作根文件系统(1.29.0) 一. 下载BusyBox BusyBox是一个继承了大量Linux命令核工具的软件,像常用的ls、cp、mv、ifconfig等命令。一般下载BusyBox的源码,然后配置Busybox,选择自己想要的功能,最后编译即可。 BusyBox在官方可以直接下载:https://www.busybox.net/。目前最新是1.35.0,这里我使用1.29.0版本。 axel https://www.busybox.net/downloads/busybox-1.29.0.tar.bz2 下载之后解压: tar 阅读详情

相关推荐

GPU运维面试题

【代码】GPU运维面试题。

u011220233的博客 700

Android客户端性能优化

这是由魅族资深Android开发工程师总结的一些优化经验,很多个方面都值得我们去着重优化,比如启动速度、过度描绘、异常的处理、耗电等等,都是我们平常没有多大关注的问题,分享给大家,可以看看哪些是自己app当中需要或可以进行优化的。 原文地址:http://blog.tingyun.com/web/article/detail/155 一、 性能检查项 1. 启动速度 1)这

By MasterChen 1280

Streamlit安装避坑指南:从零到一键启动你的第一个数据可视化应用

本文提供了一份详尽的Streamlit安装避坑指南,帮助用户从零开始快速启动第一个数据可视化应用。文章深入剖析了安装过程中常见的网络超时、依赖冲突、环境变量缺失等核心问题,并给出了使用虚拟环境、配置国内镜像源、利用.whl文件离线安装等多种经过验证的解决方案,确保安装过程顺畅无阻。

weixin_29065015的博客 616

Android客户端性能优化(魅族资深工程师毫无保留奉献)

众所周知,一个好的产品,除了功能强大,好的性能也必不可少。有调查显示,近90%的受访者会因为APP性能差而卸载,性能也是造成APP用户沮丧的头号原因。 那Android客户端性能的指标都有哪些?如何发现和定位客户端的性能问题?本文结合多个项目的开发实践,给出了要关注的重要指标项目,以及定位和解决性能问题的一般步骤。 性能优化应该贯穿于功能开发的全部周期,而不是做完一次后面便不再关注。每

2391

EtherCAT同步模式实战:如何用TwinCAT配置DC-Synchronous模式(附时序图详解)

本文详细解析了如何在TwinCAT环境中配置EtherCAT的DC-Synchronous同步模式,实现纳秒级同步精度。通过硬件准备、参数配置和高级调优步骤,帮助工程师解决工业自动化中的同步挑战,提升运动控制性能。

gold的博客 1573

【系列05】端侧AI:构建与部署高效的本地化AI模型 第4章:模型量化(Quantization)

量化的基本思想是减少模型中用于表示参数和激活值的比特数。在模型训练时,参数通常使用32位浮点数(FP32)进行存储,这提供了高精度,但也消耗大量的内存和计算资源。量化则将这些32位浮点数转换成低比特数表示,通常是8位整数(INT8)。量化的原理可以概括为:对浮点数范围进行校准,并将其映射到更小的整数范围内。例如,将一个FP32的权重(如-1.5到1.5)映射到INT8的范围(-128到127)。在推理过程中,模型将使用这些低精度的整数进行计算,从而大大减少了所需的计算量。量化带来的主要收益减少模型大小。

学习,输出==》再学习再输出 1218

【Android中级工程师】性能优化

前言最近公司培训期的项目接近尾声,之前在大学做项目都是把功能做完,写篇总结就算结束了,现在开始工作了还是觉得需要做点什么来优化一下项目。网上有很多关于性能优化的文章和方法,参考着他们的文章操作和学习,在此做点总结。

旅途的乞讨者的博客 424

YOLOv8_obb训练流程-原理解析[旋转目标检测理论篇]

本文主要介绍了YOLOv8旋转目标检测的流程,介绍了标签的解码、预测结果的解码,以及如何理解旋转角度等内容,还介绍旋转目标检测框的正样本选取及Loss计算。

ice 4732

客户端启动性能优化实践

https://blog.youkuaiyun.com/yujiankk/article/details/17251529https://blog.youkuaiyun.com/jsutluo/article/details/6725461https://blog.youkuaiyun.com/suhuaiqiang_janlay/article/details/51934024https://code.google.com/arc...

blacet的专栏 817

11、牛转录组分析的实用生物信息学流程

本文详细介绍了一套实用的牛转录组分析生物信息学流程,涵盖从数据提取、基因组索引生成、读取比对到单样本表达分析及差异表达分析的完整步骤。使用Angus和Brahman牛的RNA-seq数据作为示例,介绍了HTSEQ、featureCounts和StringTie等工具在基因表达计数中的应用,并结合edgeR和limma进行差异表达分析。文中提供了详细的命令行与R代码示例,包含常见问题解答与关键注意事项,帮助研究人员高效、准确地完成转录组数据分析。

ios99的博客 112

【微电网优化】基于粒子群求解CHP机组、气网、电网、储热罐和电锅炉微电网优化模型附matlab代码

1 简介 我国风力发电近年发展迅速,装机容量已成为全球首位.随着风力发电在电力系统中的渗透率不断提高,我国多个地区(尤其是"三北"地区)已经面临着十分严峻的风电消纳问题,产生不容忽视的弃风问题.针对目前我国风电消纳存在的困难,本文提出粒子群优化CHP机组、气网、电网、储热罐和电锅炉微电网控制策略. 2 部分代码 Ppv=[0;0;0;0;0;0;9.86000000000000;19.0100000000000;33.1000000000000;45.0700000000000;64.7900000

qq_59747472的博客 672

2024年安卓最全Android 客户端性能优化(魅族资深工程师毫无保留奉献),2024年最新androidstudio学习

给大家送上我成功跳槽复习中所整理的资料,由于文章篇幅有限,所以只是把题目列出来了网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。需要这份系统化学习资料的朋友,可以戳这里获取一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

2401_84558498的博客 355

【深度学习新浪潮】AI 智能眼镜关键视觉技术、技术栈及开源项目全解析

Meta新款智能眼镜在演示中暴露出的AI误判和延迟问题,揭示了端侧视觉与多模态算法落地的核心瓶颈。本文从算法工程视角解析了AI智能眼镜的三大关键技术:感知增强(多帧降噪、HDR成像)、场景解析(轻量化目标检测、语义分割)和空间定位(视觉SLAM、ToF辅助),并梳理了完整的技术栈架构,包括硬件适配、驱动优化和框架选型。文章还提供了高价值开源项目参考,如OpenXR和ORB-SLAM3,为端侧视觉算法落地提供实操指南,助力开发者攻克算力约束下的实时性、精度和功耗平衡难题。

专注:太空算力、AI infra、异构调度、大模型成本工程 530
上一篇: 20场面试斩获大厂offer,你在我这能学到什么?
下一篇: 程序员如何在996高压之下,求得一线生机?
懂你的大海
博客等级 码龄6年 9049粉丝 1381原创
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值