问题
在我的上一篇文章中,写了自定义弧形SeekBar,效果达到了自己的预期,于是高高兴兴回家了。但是后面手贱,在家里自己随意玩了玩,发现SeekBar滑动几下之后再滑动就会变得特别卡。然后查看代码,短时间内没什么头绪。
没错,这个时候又要祭出我的室友了。
室友之前是做rom相关的,对于android系统工具用得很熟。然后他拿着我的手机打开开发者选项中的GPU呈现模式分析
,运行了一下程序,滑了一会之后就这样了:
我们可以看到一条绿线,这条绿线代表的是60帧,超过这条线就代表不足60帧,那么人眼看起来就会感觉卡顿,可以看到超出了好多了,难怪会很卡~。
那么问题可以大致定位到绘制View的方法不够科学
。
那么怎样才能科学呢?其实我也没答案。但是大致有了一个思路:绘制好弧线和圆球之后,在滑动的时候不再重绘弧线和圆球,仅仅改变圆球的位置,这样就会少了很多的绘制操作。如此实现的话或许便能解决问题了。但也只是假设,下面开始实战。
解决方案
我将代码拆分成3个类:继承自FrameLayout的ArcSeekBarParent
,SeekBarArcView
以及SeekBarBallView
。
ArcSeekBarParent代码:
1 | public class ArcSeekBarParent extends FrameLayout implements SeekBarBallView.OnSmoothScrollListener { |
SeekBarArcView代码:
1 | public class SeekBarArcView extends View { |
SeekBarBallView代码:
1 | public class SeekBarBallView extends View { |
可以看到代码基本都是差不多的,只不过我将之前的View拆分成一个ViewGroup,绘制弧线的SeekBarArcView
和绘制圆球的SeekBarBallView
。在ACTION_MOVE的时候,我只是使用ball.layout()方法,即只改变圆球的layout,而没有重绘整个SeekBar。
添加xml引用:
1 | <com.android.lovesixgod.customarcseekbar.seekbar.ArcSeekBarParent |
然后运行,进行滑动。
可以看到GPU分析显示的线条基本不会超过绿线,滑起来也没有明显的卡顿,问题应该算是解决了~
代码已更新至Github。
小结
- 自定义View的时候尽量避免不变View的重绘。因为弧形线这个View是没有任何改变的,但是还不停地重绘,可能就会导致这样的性能问题了。
- Scroller的使用是针对View的,对于ViewGroup好像是无效的,所以我将Scroller写在了
SeekBarBallView
中。另外Scroller要能正常使用,在startScroll()
以及computeScroll()
需要invalidate()
或者postInvalidate
。 - 多使用相关工具,来观察代码的性能。