getView()被无限的循环的调用;这样消耗了大量的内存导致listview上下滑动的时候,出现了卡顿。原因就在于measure过
程,ListView一般都会根据屏幕加载多个Item,而且也会同时显示这些已经加载过的若干组Item,而这些Item的父元素都是这个
ListView。
通过Google的解释:View在Draw的时候分成两个阶段:measure和layout,在measure阶段时主要就是为了计算两个参
数:height和width。而且要注意的是,这是个递归的过程,从顶向下,DecorView开始依次调用自己子元素的measure。计算完成这两
个参数后就开始layout,最后再是draw的调用。对于ListView,当然每一个Item都会被调用Measure方法,而在这个过程中
getView和getCount会被调用,而且看用户的需求,可能会有很多次调用。问题就在于在layout中的决定ListView或者它的父元素的
height和width属性的定义了。 根据我的经验,height和width最好都设置成fill_parent,这样能避免listview对getView的疯狂调用。 解决方法就是尽量避免自适应,除非是万不得已,固定大小或者填充的效果会比较好一些。 还有一点请注意,如果使用了上面的动态测量来设置listview的显示高度,并使用了fill_parent来设置了listview的属性,但是仍然不能停止adapter中getView()方法的疯狂调用;或者还伴有listview内容显示仍然不完全现象; 根据我自己的实践经验来讲,你可以这样做: 把listview放置在LinearLayout中,<LinearLayout中只存在一个listview>我推断是,当你通过动态测量加载的时候,ta需要一个独立的空间。
渲染机制介绍
为了分析UI卡顿,我们有必要理解一下渲染机制,这套渲染机制适用于绝大部分的屏幕渲染,其中包括Android手机等众多屏幕设备。
渲染的一些重要参数:
屏幕刷新理想的频率(硬件的角度):60Hz
理想的一秒内绘制的帧数,帧率(屏幕刷新的角度):60fps
这两个参数都是理想值,指代的都是同一个概念。实际情况中难免会比它们低。在60fps内,系统会得到发送的VSYNC(垂直刷新/绘制)信号去进行渲染,就会正常地绘制出我们需要的图形界面。Android手机进行绘制的时候,GPU帮助我们将UI组件等计算成纹理Texture和三维图形Polygons,同时会使用OpenGL---会将纹理和Polygons缓存在GPU内存里面。
其中,VSYNC:有两个概念
Refresh Rate:屏幕在一秒时间内刷新屏幕的次数----有硬件的参数决定,比如60HZ,即屏幕每秒刷新60次
Frame Rate:GPU在一秒内绘制 *** 作的帧数,比如:60fps,
基本结论
要达到60fps,就要求:每一帧只能停留16ms。(大概就是1000ms/60 ~= 16ms刷新一次)
内存抖动是因为大量的对象被创建又在短时间内马上被释放。
瞬间产生大量的对象会严重占用Young Generation的内存区域,当达到阀值,剩余空间不够的时候,也会触发GC。即使每次分配的对象占用了很少的内存,但是他们叠加在一起会增加Heap的压力,从而触发更多其他类型的GC。这个 *** 作有可能会影响到帧率,并使得用户感知到性能问题。
Android里面是一个三级Generation的内存模型,最近分配的对象会存放在Young Generation区域,当这个对象在这个区域停留的时间达到一定程度,它会被移动到Old Generation,最后到Permanent Generation区域。
Android每个16ms就会绘制一次Activity,通过上述的结论我们知道,如果由于一些原因导致了我们的逻辑、CPU耗时、GPU耗时大于16ms( 应用卡顿的根源就在于16ms内不能完成绘制渲染合成过程,16ms需要完成视图树的所有测量、布局、绘制渲染及合成 ),UI就无法完成一次绘制,那么就会造成卡顿。
比如说,在16ms内,发生了频繁的GC:
在第一个16ms内,UI正常地完成了绘制,那么屏幕不会卡顿。
在第二个16ms内,由于某些原因触发了频发的GC,UI无法在16ms内完成绘制,就会卡顿。
UI卡顿外部和内部常见原因
下面总结一些常见的UI卡顿原因:
1.内存抖动的问题
2.方法太耗时了(CPU占用)
1) CPU计算时间,CPU的测量、布局时间
2)CPU将计算好的Polygons和Texture传递到GPU的时候也需要时间。OpenGL ES API允许数据上传到GPU后可以对数据进行保存,缓存到display list。因此,我们平移等 *** 作一个view是几乎不怎么耗时的 。
3) GPU进行格栅化
当我们的布局是用的FrameLayout的时候,我们可以把它改成merge,可以避免自己的帧布局和系统的ContentFrameLayout帧布局重叠造成重复计算(measure和layout)。
使用ViewStub:当加载的时候才会占用。不加载的时候就是隐藏的,仅仅占用位置。
CPU优化建议
针对CPU的优化,从减轻加工View对象成Polygons和Texture来下手:
View Hierarchy中包涵了太多的没有用的view,这些view根本就不会显示在屏幕上面,一旦触发测量和布局 *** 作,就会拖累应用的性能表现。那么我们就需要利用工具进行分析。
如何找出里面没用的view呢?或者减少不必要的view嵌套。
我们利用工具:Hierarchy Viewer进行检测,优化思想是:查看自己的布局,层次是否很深以及渲染比较耗时,然后想办法能否减少层级以及优化每一个View的渲染时间。
我们打开APP,然后打开Android Device Monitor,然后切换到Hierarchy Viewer面板。除了看层次结构之外,还可以看到一些耗时的信息:
三个圆点分别代表:测量、布局、绘制三个阶段的性能表现。
1)绿色:渲染的管道阶段,这个视图的渲染速度快于至少一半的其他的视图。
2)黄色:渲染速度比较慢的50%。
3)红色:渲染速度非常慢。
GPU优化建议就是一句话:尽量避免过度绘制(overdraw)
一、背景经常容易造成过度绘制。
手机开发者选项里面找到工具:Debug GPU overdraw,其中,不同颜色代表了绘制了几次:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)