SquareGridView性能优化

作者: rain 分类: 移动 发布时间: 2013-01-09 15:01 6 条评论

在前一篇 Android实现自适应正方形GridView中,虽然实现了正方形GridItem效果,但是如果用Android 性能分析案例 中 提到的方式来看看Overdraw问题比较严重。

先看看截图:

SquareGridView的Overdraw问题

SquareGridView的Overdraw问题

蓝色代表一次过度绘制,绿色代表二次过度绘制,而浅红色代表三次过度绘制, 和 Falcon Pro  应用比起来还算不错,没有大面积的浅红色和红色。 \(^o^)/~

如果您只满足于此,则可以跳过下面的 文字了, ^_^。 这篇文章的目标是把上图的效果优化为下图的效果:

优化后的SquareGridView

优化后的SquareGridView

上图看起来怎么样?只有少量的一次过度绘制和二次过度绘制, 超过三次的过度绘制只出现在按下状态一个Item中。

如果您对如何实现上面优化过的效果感兴趣,请继续阅读!

消除过度绘制

首先去掉Activity的背景,可以通过自定义Theme实现也可以通过在MainActivity的onCreate函数中设置窗口背景来实现,

然后再次运行程序,发现头像区域已经从绿色(二次过度绘制)变为蓝色(一次过度绘制)了,这里头像的一次过度绘制是由于GridView的背景导致的,和 Android 性能分析案例  中 Falcon Pro  应用 的图片背景原因一样。 要修改这个问题 我们需要把GridView的背景取消,然后设置GridView的android:horizontalSpacing 和 android:verticalSpacing 为0,修改后的activity_main.xml中的GridView   代码如下:

而每个图片的边框通过在每个GridItem上绘制边框背景实现,在item.xml布局文件中给 org.goodev.squaregrid.SquareLayout添加边框背景android:background

上面的背景对应drawable目录下的grid_item_border.xml文件

注意:上面使用了selector,来支持不同状态的边框颜色修改,如果无此需求,则可以直接在org.goodev.squaregrid.SquareLayout中设置背景为@drawable/item_border。
item_border.xml文件内容如下:

按照上面的方式修改后,头像区域就没有过度绘制了,感兴趣的同学可以下载这个APK在手机上运行下看看效果。

最后一行的残影问题

由于GridView显示的数目不一定刚好可以填充最后一行,比如一共显示10个条目,一行显示3个,那么第三行就只显示第一个,而后面两个是空白的。 按照上面的时候,当用户滚动到最后一行的时候, 由于后面两个是空白的,没有像素的区域,系统不会重绘这两个Item所占的区域,会导致滚动后显示上一行内容留下的残影

最后一行的残影

最后一行的残影

要解决这个问题,则需要自定义GridView,在布局的时候计算显示Item的个数和每行显示几个item. 看看最后一行是否填满,如果没有则用NULL item补充,在GridAdapter判断为NULL item的时候,返回一个特殊的背景View即可。

创建一个org.goodev.squaregrid.OptimizeGridView类,代码如下

覆写了 GridView的onMeasure类,GridView调用完该类后会计算出每行显示多少个Item,具体数字保存在变量mNumColumns中,而在Api 11之前版本我们只能通过反射来获取该变量的值。
在上面的类中还定义了一个接口OptimizeGridAdapter,该接口定义了几个函数用来支持添加NULL item到Adapter中来填充最后一行。

然后修改org.goodev.squaregrid.GridAdapter类实现OptimizeGridAdapter接口即可。

最后修改activity_main.xml布局文件使用新的 org.goodev.squaregrid.OptimizeGridView 自定义GridView即可

完成上面修改 再运行程序,可以看到现在的结果如下图所示,没有残影了。

解决残影的截图

解决残影的截图

感兴趣的同学可以下载这个APK体验下。

GridView四周的边框
细心的同学可能发现了,由于GridItem的边框是在Item View中实现的,所以在GridView四周也会出现这个边框,如上图左右的紫色边框和下方的紫色边框。消除该边框也是非常简单的,只需要设置GridView的layout_marginXXX值为item边框的负值即可。
在activity_main.xml中的org.goodev.squaregrid.OptimizeGridView控件上添加layout_margin属性:

android:id=”@+id/grid”
android:layout_marginLeft=”@dimen/gridMarginTopLeft”
android:layout_marginRight=”@dimen/gridMarginBottomRight”
android:layout_marginTop=”@dimen/gridMarginTopLeft”
android:layout_marginBottom=”@dimen/gridMarginBottomRight”

最终结果如下:

消除GridView 四周的边框

消除GridView 四周的边框

完成的示例APK下载 https://github.com/goodev/SquareGridView/raw/master/SquareGrid/apks/OptimizeSquareGrid.apk

示例代码 https://github.com/goodev/SquareGridView/tree/master/OptimizeSquareGrid

最后来看看陌陌搜索结果界面的Overdraw情况,感兴趣的可以研究下是哪里地方引起了这些Overdraw。

陌陌3.0.1 版本上的Overdraw

陌陌3.0.1 版本上的Overdraw

update 2013年3月28日

在实现选中效果的时候,可以设置GridView的属性:android:drawSelectorOnTop=”true” ,这样选中效果就绘制在Item上面而不是下面, 这样可以减少那个选中效果View。效率更好。

本文出自 云在千峰,转载时请注明出处及相应链接。

本文永久链接: http://blog.chengyunfeng.com/?p=466

Ɣ回顶部