深圳网站平台建设,网上销售平台,php外贸网站,做视频素材哪个网站好目录一、四个方面二、卡顿优化1、Android系统显示原理2、卡顿根本原因3、性能分析工具#xff08;1#xff09;Profile GPU Rendering#xff08;2#xff09;TraceView#xff08;3#xff09;Systrace UI 性能分析4、优化建议#xff08;1#xff09;布局优化#x…
目录一、四个方面二、卡顿优化1、Android系统显示原理2、卡顿根本原因3、性能分析工具1Profile GPU Rendering2TraceView3Systrace UI 性能分析4、优化建议1布局优化2避免过度绘制3启动优化4合理的刷新机制5其他三、内存优化1、Android内存管理机制1Java对象生命周期2内存分配3内存回收机制2、内存分析工具1Memory Monitor2Heap Viewer3Allocation Tracker4Memory Analyzer Tool(MAT)3、常见内存泄漏场景4、优化内存空间四、稳定性优化五、耗电优化六、安装包大小优化一、四个方面
可以把用户体验的性能问题主要总结为4个类别 流畅 稳定 省电、省流量 安装包小
性能问题的主要原因是什么原因有相同的也有不同的但归根到底不外乎内存使用、代码效率、合适的策略逻辑、代码质量、安装包体积这一类问题整理归类如下 从图中可以看到打造一个高质量的应用应该以4个方向为目标快、稳、省、小。 快使用时避免出现卡顿响应速度快减少用户等待的时间满足用户期望。 稳减低 crash 率和 ANR 率不要在用户使用过程中崩溃和无响应。 省节省流量和耗电减少用户使用成本避免使用时导致手机发烫。 小安装包小可以降低用户的安装成本。
要想达到这4个目标具体实现是在右边框里的问题卡顿、内存使用不合理、代码质量差、代码逻辑乱、安装包过大这些问题也是在开发过程中碰到最多的问题在实现业务需求同时也需要考虑到这点多花时间去思考如何避免功能完成后再来做优化不然的话等功能实现后带来的维护成本会增加。 二、卡顿优化
Android 应用启动慢使用时经常卡顿是非常影响用户体验的应该尽量避免出现。卡顿的场景有很多按场景可以分为4类UI 绘制、应用启动、页面跳转、事件响应如图
这4种卡顿场景的根本原因可以分为两大类 界面绘制主要原因是绘制的层级深、页面复杂、刷新不合理由于这些原因导致卡顿的场景更多出现在UI和启动后的初始界面以及跳转到页面的绘制上。 数据处理导致这种卡顿场景的原因是数据处理量太大一般分为三种情况一是数据在处理UI线程二是数据处理占用CPU高导致主线程拿不到时间片三是内存增加导致GC频繁从而引起卡顿。
引起卡顿的原因很多但不管怎么样的原因和场景最终都是通过设备屏幕上显示来达到用户归根到底就是显示有问题所以要解决卡顿就要先了解Android系统的显示原理。 1、Android系统显示原理
Android显示过程可以简单概括为Android应用程序把经过测量、布局、绘制后的Surface缓存数据通过SurfaceFlinger把数据渲染到显示屏幕上 通过Android的刷新机制来刷新数据。也就是说应用层负责绘制系统层负责渲染通过进程间通信把应用层需要绘制的数据传递到系统层服务系统层服务通过刷新机制把数据更新到屏幕上。
我们都知道在Android的每个View绘制中有三个核心步骤Measure、Layout、Draw。具体实现是从 ViewRootImp类的performTraversals() 方法开始执行Measure和Layout都是通过递归来获取View的大小和位置并且以深度作为优先级可以看出 层级越深、元素越多、耗时也就越长。
真正把需要显示的数据渲染到屏幕上是通过系统级进程中的SurfaceFlinger服务来实现的那么这个SurfaceFlinger服务主要做了哪些工作呢如下 响应客户端事件创建Layer与客户端的Surface建立连接。 接收客户端数据及属性修改Layer属性如尺寸、颜色、透明度等。 将创建的Layer内容刷新到屏幕上。 维持Layer的序列并对Layer最终输出做出裁剪计算。
既然是两个不同的进程那么肯定是需要一个跨进程的通信机制来实现数据传递在Android显示系统中使用了Android的匿名共享内存SharedClient每一个应用和SurfaceFlinger之间都会创建一个SharedClient 然后在每个SharedClient中最多可以创建31个 SharedBufferStack每个Surface都对应一个SharedBufferStack也就是一个Window。
一个SharedClient对应一个Android应用程序而一个Android应用程序可能包含多个窗口即Surface。也就是说SharedClient包含的是SharedBufferStack的集合其中在显示刷新机制中用到了双缓冲和三重缓冲技术。最后总结起来显示整体流程分为三个模块应用层绘制到缓存区SurfaceFlinger把缓存区数据渲染到屏幕由于是不同的进程所以使用Android的匿名共享内存SharedClient缓存需要显示的数据来达到目的。
除此之外我们还需要一个名词FPS。FPS表示每秒传递的帧数。在理想情况下60FPS就感觉不到卡这意味着每个绘制时长应该在16ms以内。但是 Android系统很有可能无法及时完成那些复杂的页面渲染操作。Android系统每隔16ms发出VSYNC信号触发对UI进行渲染如果每次渲染都成功这样就能够达到流畅的画面所需的60FPS。如果某个操作花费的时间是24ms 系统在得到VSYNC信号时就无法正常进行正常渲染这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面这种现象在执行动画或滑动列表比较常见还有可能是你的Layout太过复杂层叠太多的绘制单元无法在16ms完成渲染最终引起刷新不及时。 2、卡顿根本原因
根据Android系统显示原理可以看到影响绘制的根本原因有以下两个方面 绘制任务太重绘制一帧内容耗时太长。 主线程太忙根据系统传递过来的VSYNC信号来时还没准备好数据导致丢帧。
绘制耗时太长有一些工具可以帮助我们定位问题。主线程太忙则需要注意了主线程关键职责是处理用户交互在屏幕上绘制像素并进行加载显示相关的数据所以特别需要避免任何主线程的事情这样应用程序才能保持对用户操作的即时响应。总结起来主线程主要做以下几个方面工作 UI生命周期控制 系统事件处理 消息处理 界面布局 界面绘制 界面刷新
除此之外应该尽量避免将其他处理放在主线程中特别复杂的数据计算和网络请求等。 3、性能分析工具
性能问题并不容易复现也不好定位但是真的碰到问题还是需要去解决的那么分析问题和确认问题是否解决就需要借助相应的的调试工具比如查看Layout层次的Hierarchy View、Android系统上带的GPU Profile工具和静态代码检查工具Lint等这些工具对性能优化起到非常重要的作用所以要熟悉知道在什么场景用什么工具来分析。 1Profile GPU Rendering
在手机开发者模式下有一个卡顿检测工具叫做Profile GPU Rendering如图
它的功能特点如下 一个图形监测工具能实时反应当前绘制的耗时 横轴表示时间纵轴表示每一帧的耗时 随着时间推移从左到右的刷新呈现 提供一个标准的耗时如果高于标准耗时就表示当前这一帧丢失 2TraceView
TraceView是Android SDK自带的工具用来分析函数调用过程可以对Android的应用程序以及Framework层的代码进行性能分析。它是一个图形化的工具最终会产生一个图表用于对性能分析进行说明可以分析到每一个方法的执行时间其中可以统计出该方法调用次数和递归次数实际时长等参数维度使用非常直观分析性能非常方便。 3Systrace UI 性能分析
Systrace是Android 4.1及以上版本提供的性能数据采样和分析工具它是通过系统的角度来返回一些信息。它可以帮助开发者收集Android关键子系统如Surfaceflinger、WindowManagerService等Framework部分关键模块、服务、View系统等运行信息从而帮助开发者更直观地分析系统瓶颈改进性能。Systrace的功能包括跟踪系统的I/O操作、内核工作队列、CPU负载等在UI显示性能分析上提供很好的数据特别是在动画播放不流畅、渲染卡等问题上。 4、优化建议
布局优化避免过度绘制启动优化合理的刷新机制其他 1布局优化
布局是否合理主要影响的是页面测量时间的多少我们知道一个页面的显示测量和绘制过程都是通过递归来完成的多叉树遍历的时间与树的高度h有关其时间复杂度O(h)如果层级太深每增加一层则会增加更多的页面显示时间所以布局的合理性就显得很重要。
那布局优化有哪些方法呢主要通过 减少层级、减少测量和绘制时间、提高复用性 三个方面入手。总结如下 减少层级合理使用RelativeLayout和LinerLayout合理使用Merge。 提高显示速度使用ViewStub它是一个看不见的、不占布局位置、占用资源非常小的视图对象。 布局复用可以通过标签include来提高复用。 尽可能少用wrap_contentwrap_content 会增加布局measure时计算成本在已知宽高为固定值时不用wrap_content。 其他删除控件中无用的属性。 2避免过度绘制
过度绘制是指在屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的UI结构中如果不可见的UI也在做绘制的操作就会导致某些像素区域被绘制了多次从而浪费了多余的CPU以及GPU源。
如何避免过度绘制呢如下 布局上的优化移除XML中非必须的背景移除Window默认的背景、按需显示占位背景图片。 自定义View优化使用 canvas.clipRect()来帮助系统识别那些可见的区域只有在这个区域内才会被绘制。 3启动优化
通过对启动速度的监控发现影响启动速度的问题所在优化启动逻辑提高应用的启动速度。启动主要完成三件事UI布局、绘制和数据准备。因此启动速度优化就是需要优化这三个过程 UI布局应用一般都有闪屏页优化闪屏页的UI布局可以通过Profile GPU Rendering检测丢帧情况。 启动加载逻辑优化可以采用分布加载、异步加载、延期加载策略来提高应用启动速度。 数据准备数据初始化分析加载数据可以考虑用线程初始化等策略。 4合理的刷新机制
在应用开发过程中因为数据的变化需要刷新页面来展示新的数据但频繁刷新会增加资源开销并且可能导致卡顿发生因此需要一个合理的刷新机制来提高整体的UI流畅度。合理的刷新需要注意以下几点 尽量减少刷新次数。 尽量避免后台有高的CPU线程运行。 缩小刷新区域。 5其他
在实现动画效果时需要根据不同场景选择合适的动画框架来实现。有些情况下可以用硬件加速方式来提供流畅度。 三、内存优化
在Android系统中有个垃圾内存回收机制在虚拟机层自动分配和释放内存因此不需要在代码中分配和释放某一块内存从应用层面上不容易出现内存泄漏和内存溢出等问题但是需要内存管理。Android系统在内存管理上有一个Generational Heap Memory模型内存回收的大部分压力不需要应用层关心Generational Heap Memory有自己一套管理机制当内存达到一个阈值时系统会根据不同的规则自动释放系统认为可以释放的内存也正是因为Android程序把内存控制的权力交给了Generational Heap Memory一旦出现内存泄漏和溢出方面的问题排查错误将会成为一项异常艰难的工作。除此之外部分Android应用开发人员在开发过程中并没有特别关注内存的合理使用也没有在内存方面做太多的优化当应用程序同时运行越来越多的任务加上越来越复杂的业务需求时完全依赖Android的内存管理机制就会导致一系列性能问题逐渐呈现对应用的稳定性和性能带来不可忽视的影响因此解决内存问题和合理优化内存是非常有必要的。 1、Android内存管理机制
Android应用都是在 Android的虚拟机上运行应用 程序的内存分配与垃圾回收都是由虚拟机完成的。在Android系统虚拟机有两种运行模式Dalvik和ART。
1Java对象生命周期 一般Java对象在虚拟机上有7个运行阶段
创建阶段-应用阶段-不可见阶段-不可达阶段-收集阶段-终结阶段-对象空间重新分配阶段 2内存分配
在Android系统中内存分配实际上是对堆的分配和释放。当一个Android程序启动应用进程都是从一个叫做Zygote的进程衍生出来系统启动 Zygote 进程后为了启动一个新的应用程序进程系统会衍生Zygote进程生成一个新的进程然后在新的进程中加载并运行应用程序的代码。其中大多数的RAM pages被用来分配给Framework代码同时促使RAM资源能够在应用所有进程之间共享。
但是为了整个系统的内存控制需要Android系统会为每一个应用程序都设置一个硬性的Dalvik Heap Size最大限制阈值整个阈值在不同设备上会因为RAM大小不同而有所差异。如果应用占用内存空间已经接近整个阈值时再尝试分配内存的话就很容易引起内存溢出的错误。 3内存回收机制
我们需要知道的是在Java中内存被分为三个区域Young Generation(新生代)、Old Generation(年老代)、Permanent Generation(持久代)。最近分配的对象会存放在Young Generation区域。对象在某个时机触发GC回收垃圾而没有回收的就根据不同规则有可能被移动到Old Generation最后累积一定时间在移动到Permanent Generation 区域。系统会根据内存中不同的内存数据类型分别执行不同的GC操作。GC通过确定对象是否被活动对象引用来确定是否收集对象进而动态回收无任何引用的对象占据的内存空间。但需要注意的是频繁的GC会增加应用的卡顿情况影响应用的流畅性因此需要尽量减少系统GC行为以便提高应用的流畅度减小卡顿发生的概率。 2、内存分析工具
做内存优化前需要了解当前应用的内存使用现状通过现状去分析哪些数据类型有问题各种类型的分布情况如何以及在发现问题后如何发现是哪些具体对象导致的这就需要相关工具来帮助我们。 1Memory Monitor
Memory Monitor是一款使用非常简单的图形化工具可以很好地监控系统或应用的内存使用情况主要有以下功能 显示可用和已用内存并且以时间为维度实时反应内存分配和回收情况。 快速判断应用程序的运行缓慢是否由于过度的内存回收导致。 快速判断应用是否由于内存不足导致程序崩溃。 2Heap Viewer
Heap Viewer的主要功能是查看不同数据类型在内存中的使用情况可以看到当前进程中的Heap Size的情况分别有哪些类型的数据以及各种类型数据占比情况。通过分析这些数据来找到大的内存对象再进一步分析这些大对象进而通过优化减少内存开销也可以通过数据的变化发现内存泄漏。 3Allocation Tracker
Memory Monitor和Heap Viewer都可以很直观且实时地监控内存使用情况还能发现内存问题但发现内存问题后不能再进一步找到原因或者发现一块异常内存但不能区别是否正常同时在发现问题后也不能定位到具体的类和方法。这时就需要使用另一个内存分析工具Allocation Tracker进行更详细的分析Allocation Tracker可以分配跟踪记录应用程序的内存分配并列出了它们的调用堆栈可以查看所有对象内存分配的周期。 4Memory Analyzer Tool(MAT)
MAT是一个快速功能丰富的Java Heap分析工具通过分析Java进程的内存快照HPROF分析从众多的对象中分析快速计算出在内存中对象占用的大小查看哪些对象不能被垃圾收集器回收并可以通过视图直观地查看可能造成这种结果的对象。 3、常见内存泄漏场景
如果在内存泄漏发生后再去找原因并修复会增加开发的成本最好在编写代码时就能够很好地考虑内存问题写出更高质量的代码这里列出一些常见的内存泄漏场景在以后的开发过程中需要避免这类问题。 资源性对象未关闭比如Cursor、File文件等往往都用了一些缓冲在不使用时应该及时关闭它们。 注册对象未注销比如事件注册后未注销会导致观察者列表中维持着对象的引用。 类的静态变量持有大数据对象。 非静态内部类的静态实例。 Handler临时性内存泄漏如果Handler是非静态的容易导致Activity或Service不会被回收。 容器中的对象没清理造成的内存泄漏。 WebViewWebView存在着内存泄漏的问题在应用中只要使用一次WebView内存就不会被释放掉。
除此之外内存泄漏可监控常见的就是用LeakCanary第三方库这是一个检测内存泄漏的开源库使用非常简单可以在发生内存泄漏时告警并且生成leak tarce分析泄漏位置同时可以提供Dump文件进行分析。 4、优化内存空间
没有内存泄漏并不意味着内存就不需要优化在移动设备上由于物理设备的存储空间有限Android 系统对每个应用进程也都分配了有限的堆内存因此使用最小内存对象或者资源可以减小内存开销同时让GC 能更高效地回收不再需要使用的对象让应用堆内存保持充足的可用内存使应用更稳定高效地运行。常见做法如下 对象引用强引用、软引用、弱引用、虚引用四种引用类型根据业务需求合理使用不同选择不同的引用类型。 减少不必要的内存开销注意自动装箱增加内存复用比如有效利用系统自带的资源、视图复用、对象池、Bitmap对象的复用。 使用最优的数据类型比如针对数据类容器结构可以使用ArrayMap数据结构避免使用枚举类型使用缓存Lrucache等等。 图片内存优化可以设置位图规格根据采样因子做压缩用一些图片缓存方式对图片进行管理等等。 四、稳定性优化
Android应用的稳定性定义很宽泛影响稳定性的原因很多比如内存使用不合理、代码异常场景考虑不周全、代码逻辑不合理等都会对应用的稳定性造成影响。其中最常见的两个场景是Crash和ANR这两个错误将会使得程序无法使用比较常用的解决方式如下 提高代码质量比如开发期间的代码审核看些代码设计逻辑业务合理性等。 代码静态扫描工具常见工具有Android Lint、Findbugs、Checkstyle、PMD等等。 Crash监控把一些崩溃的信息异常信息及时地记录下来以便后续分析解决。 Crash上传机制在Crash后尽量先保存日志到本地然后等下一次网络正常时再上传日志信息。 五、耗电优化
在移动设备中电池的重要性不言而喻没有电什么都干不成。对于操作系统和设备开发商来说耗电优化一致没有停止去追求更长的待机时间而对于一款应用来说并不是可以忽略电量使用问题特别是那些被归为“电池杀手”的应用最终的结果是被卸载。因此应用开发者在实现需求的同时需要尽量减少电量的消耗。
在Android5.0以前在应用中测试电量消耗比较麻烦也不准确5.0之后专门引入了一个获取设备上电量消耗信息的API:Battery Historian。Battery Historian是一款由Google提供的Android系统电量分析工具和Systrace一样是一款图形化数据分析工具直观地展示出手机的电量消耗过程通过输入电量分析文件显示消耗情况最后提供一些可供参考电量优化的方法。
除此之外还有一些常用方案可提供 计算优化避开浮点运算等。 避免WaleLock使用不当。 使用Job Scheduler。 六、安装包大小优化
应用安装包大小对应用使用没有影响但应用的安装包越大用户下载的门槛越高特别是在移动网络情况下用户在下载应用时对安装包大小的要求更高因此减小安装包大小可以让更多用户愿意下载和体验产品。
常用应用安装包的构成如图所示
从图中我们可以看到 assets文件夹存放一些配置文件、资源文件assets不会自动生成对应的 ID而是通过AssetManager类的接口获取。 resres是resource的缩写这个目录存放资源文件会自动生成对应的ID并映射到 .R文件中访问直接使用资源ID。 META-INF保存应用的签名信息签名信息可以验证APK文件的完整性。 AndroidManifest.xml这个文件用来描述Android应用的配置信息一些组件的注册信息、可使用权限等。 classes.dexDalvik字节码程序让Dalvik虚拟机可执行一般情况下Android应用在打包时通过Android SDK中的dx工具将Java字节码转换为Dalvik字节码。 resources.arsc记录着资源文件和资源ID之间的映射关系用来根据资源ID寻找资源。
减少安装包大小的常用方案 代码混淆使用ProGuard代码混淆器工具它包括压缩、优化、混淆等功能。 资源优化比如使用Android Lint删除冗余资源资源文件最少化等。 图片优化比如利用AAPT工具对PNG格式的图片做压缩处理降低图片色彩位数等。 避免重复功能的库使用WebP图片格式。 插件化比如功能模块放在服务器上按需下载可以减少安装包大小。