android自定义view课程之view的优化

heavygoose 发布于7月前 阅读2204次
0 条评论

现在你有一个设计好的,对手势和状态之间的转变做出反应的view,你需要保证view能快速的运行。在播放期间,为了避免UI界面感觉呆滞和不连贯的问题,你必须保证你的动画速率始终在60帧/秒上一直运行着。

降低刷新频率

为了提高view的运行速度,减少来自于频繁调用的程序的不必要的代码。从onDraw()方法开始调用,这会给你带来最好的回报。特别地,在onDraw()方法中你应该减少冗余代码,冗余代码会带来使你view不连贯的垃圾回收。初始化的冗余对象,或者动画之间的,在动画运行时,永远都不会有所贡献。

加之为了使onDraw()方法更有依赖性,你应该尽可能的不要频繁的调用它。大部分时候调用 onDraw()方法就是调用invalidate()的结果,所以减少不必要的调用invalidate()方法。有可能的,调用四种参数不同类型的invalidate(),而不是调用无参的版本。无参变量需要刷新整个view,而四种参数类型的变量只需刷新指定部分的view.这种高效的调用更加接近需求,也能减少落在矩形屏幕外的不必 要刷新的页面。

另外奢侈的操作就是研究布局。任何时候,一个view调用requestLayou()方法,这AndroidUI 系统会穿过整个层级view来查找每一个view需要多大,如果发现冲突的尺寸,它需要多次穿过这个层级。UI设计者们创建了深层次的内置的 ViewGroup对象,为了让UI更合适的表现出来。这深层此的view会带来画面的问题,尽可能的使你的view层级关系浅显一些。

如果你有一个复杂的UI,你应该写一个自定义的ViewGroup类来表现它的布局。不同于内置的 view类,你的自定义view能关于尺寸和它子控件的形状做出应用特定的假想,同时避免通过它子类来 计算尺寸。这圆图例子显示怎样作为自定义view一部分来继承ViewGroup类,圆图有它子view类, 但是重来都不测量他们。相反地,它直接地通过自己自定义的布局算法来设定他们的尺寸大小。

使用硬件加速

作为Android3.0,Android2D图表系统可以通过大部分新的Android装置自带GPU(图表处理单元)来增加,对于许多应用程序 来说,GPU硬件加速度能带来巨大的性能增加,但是对于每一个应用来讲,并不都是正确的选择。Android框架层更好地为你提供了控制应用程序部分硬件 是否增加的能力。

怎样在你的应用,活动,或者窗体级别中使用加速度类,请查阅Android开发者指南中的Hardware Acceleration类。注意到在开发者指南中的附加说明,你必须在你的AndroidManifest.xml 文件中的<uses-sdk android:targetSdkVersion="11"/>中将应用目标API设置到11或者更高的级别。

一旦你使用硬件加速度类,你可能没有看到性能的增长,手机GPUs非常擅长某些任务,例如测量,翻转,和平移位图类的图片。特别地,他们不擅长其他的任务,例如画直线和曲线。为了利用GPU加速度类,你应该增加GPU擅长的操作数量,和减少GPU不擅长的操作数量。

在PieChart 例子中,例如,画一个饼图相对来说是比较麻烦的。每次重新画饼图,它的翻转都会给UI界面带来不流畅的感觉。解决方案就是在子View类中放置饼图和将View的布局类型设置为 LAYER_TYPE_HARDWARE,这样GPU能将它作为静态图片缓存。样例将子view作为PieChart的内部类来定义,这样减少了来自于需要实现方案的大量代码的改动。

private class PieView extends View {
 
      public PieView(Context context) {
          super(context);
          if (!isInEditMode()) {
              setLayerType(View.LAYER_TYPE_HARDWARE, null);
          }
      }
 
      @Override
      protected void onDraw(Canvas canvas) {
          super.onDraw(canvas);
 
          for (Item it : mData) {
              mPiePaint.setShader(it.mShader);
              canvas.drawArc(mBounds,
                      360 - it.mEndAngle,
                      it.mEndAngle - it.mStartAngle,
                      true, mPiePaint);
          }
      }
 
      @Override
      protected void onSizeChanged(int w, int h, int oldw, int oldh) {
          mBounds = new RectF(0, 0, w, h);
      }
 
      RectF mBounds;
  }

代码改动之后,PieChart.PieView.onDraw()方法只有在view第一次显示的时候才会被调用。在application的生 命周期的其他时间里,这饼图会作为图片缓存着,在不同角度翻转的时候被GPU重新绘制。GPU尤其擅长那些一眼就能看出性能差异的东西。

这是一个痛苦的抉择,作为硬件布局缓存图片会消耗视频内存,这是一个有限的资源。所以,只有用户在滚动活动的时候,PieChart.PieView最终版本才会将它的布局类型设置为LAYER_TYPE_HARDWARE,在其他的任何时候,它将布局类型设置为LAYER_TYPE_NONE,这将允许GPU停止缓存图片。

最后,别忘了优化你的代码。在view上增加性能的技术,将不会对其他view性能产生大的影响。


共收到0条回复

需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。