您的位置:首页 > 移动开发 > Android开发

Android setLayerType 硬件加速问题

2015-11-22 10:25 639 查看

转自:http://blog.csdn.net/shichaosong/article/details/7453778

[html]
view plaincopyprint?





/**  
   * <p>Specifies the type of layer backing this view. The layer can be  
   * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or  
   * {@link #LAYER_TYPE_HARDWARE}.</p>  
   *  
   * <p>A layer is associated with an optional {@link android.graphics.Paint}  
   * instance that controls how the layer is composed on screen. The following  
   * properties of the paint are taken into account when composing the layer:</p>  
   * <ul>  
   * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>  
   * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>  
   * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>  
   * </ul>  
   *  
   * <p>If this view has an alpha value set to < 1.0 by calling  
   * {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded  
   * by this view's alpha value.</p>  
   *  
   * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},  
   * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}  
   * for more information on when and how to use layers.</p>  
   *  
   * @param layerType The type of layer to use with this view, must be one of  
   *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or  
   *        {@link #LAYER_TYPE_HARDWARE}  
   * @param paint The paint used to compose the layer. This argument is optional  
   *        and can be null. It is ignored when the layer type is  
   *        {@link #LAYER_TYPE_NONE}  
   *  
   * @see #getLayerType()  
   * @see #LAYER_TYPE_NONE  
   * @see #LAYER_TYPE_SOFTWARE  
   * @see #LAYER_TYPE_HARDWARE  
   * @see #setAlpha(float)  
   *  
   * @attr ref android.R.styleable#View_layerType  
   */  
  public void setLayerType(int layerType, Paint paint) {  
      if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {  
          throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "  
                  + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");  
      }  
  
      if (layerType == mLayerType) {  
          if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {  
              mLayerPaint = paint == null ? new Paint() : paint;  
              invalidateParentCaches();  
              invalidate(true);  
          }  
          return;  
      }  
  
      // Destroy any previous software drawing cache if needed  
      switch (mLayerType) {  
          case LAYER_TYPE_HARDWARE:  
              destroyLayer(false);  
              // fall through - non-accelerated views may use software layer mechanism instead  
          case LAYER_TYPE_SOFTWARE:  
              destroyDrawingCache();  
              break;  
          default:  
              break;  
      }  
  
      mLayerType = layerType;  
      final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;  
      mLayerPaint = layerDisa
108bc
bled ? null : (paint == null ? new Paint() : paint);  
      mLocalDirtyRect = layerDisabled ? null : new Rect();  
  
      invalidateParentCaches();  
      invalidate(true);  
  }  

/**
* <p>Specifies the type of layer backing this view. The layer can be
* {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
* {@link #LAYER_TYPE_HARDWARE}.</p>
*
* <p>A layer is associated with an optional {@link android.graphics.Paint}
* instance that controls how the layer is composed on screen. The following
* properties of the paint are taken into account when composing the layer:</p>
* <ul>
* <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
* <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
* <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
* </ul>
*
* <p>If this view has an alpha value set to < 1.0 by calling
* {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded
* by this view's alpha value.</p>
*
* <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
* {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
* for more information on when and how to use layers.</p>
*
* @param layerType The type of layer to use with this view, must be one of
*        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
*        {@link #LAYER_TYPE_HARDWARE}
* @param paint The paint used to compose the layer. This argument is optional
*        and can be null. It is ignored when the layer type is
*        {@link #LAYER_TYPE_NONE}
*
* @see #getLayerType()
* @see #LAYER_TYPE_NONE
* @see #LAYER_TYPE_SOFTWARE
* @see #LAYER_TYPE_HARDWARE
* @see #setAlpha(float)
*
* @attr ref android.R.styleable#View_layerType
*/
public void setLayerType(int layerType, Paint paint) {
if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
+ "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
}

if (layerType == mLayerType) {
if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
mLayerPaint = paint == null ? new Paint() : paint;
invalidateParentCaches();
invalidate(true);
}
return;
}

// Destroy any previous software drawing cache if needed
switch (mLayerType) {
case LAYER_TYPE_HARDWARE:
destroyLayer(false);
// fall through - non-accelerated views may use software layer mechanism instead
case LAYER_TYPE_SOFTWARE:
destroyDrawingCache();
break;
default:
break;
}

mLayerType = layerType;
final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
mLocalDirtyRect = layerDisabled ? null : new Rect();

invalidateParentCaches();
invalidate(true);
}


参考:
http://mobile.51cto.com/hot-302203.htm http://blog.csdn.net/niu_gao/article/details/7464320
-------------------------------------------------------------------------------------------------------------------------------------------

最近听同事讨论硬件加速问题,完全不懂。于是乎,百度了下,原来从3.0开始,安卓开始支持硬件加速,手机自然是从4.0开始支持的了。而且配置方法一种是在代码中配置硬件加速,这个也分很多个级别,在minifest中;一种方式是在手机的开发人员选项中启用硬件加速,不过似乎只有google的nexus有这个选项,其它的手机都别屏蔽了。

硬件加速的官方文档:http://developer.android.com/guide/topics/graphics/hardware-accel.html

开启硬件加速有两种大的途径

1.在系统设置“开发人员……”中勾选启用GPU加速

2.在应用程序中启用硬件加速

目前遇到的问题有,启用硬件加速后,WebView的性能受到一定影响,设置背景透明无效。

目前4.0的系统有硬件加速,之前的版本不太清楚。

我们来看怎样在程序中启用硬件加速

if (VERSION.SDK_INT > VERSION_SDK_ELEVEN)
{
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
}

这是,Window级别的硬件加速就启动了。

对于已经在系统设置项中开启硬件加速,但是硬件加速会给应用程序带来问题的情况,可以使用如下方法为应用程序View级别取消硬件加速

mView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

这里有篇非常棒的文章:

转载时请注明出处和作者联系方式: http://mogoweb.net mogoweb@gmail.com

本文的主要内容来自SDK文章的"Hardware Acceleration”.

从Android 3.0开始,Android的2D渲染管线可以更好的支持硬件加速。硬件加速使用GPU进行View上的绘制操作。

硬件加速可以在一下四个级别开启或关闭:

Application
Activity
Window
View

Application级别

往您的应用程序AndroidManifest.xml文件为application标签添加如下的属性即可为整个应用程序开启硬件加速:

<application android:hardwareAccelerated="true" ...>

Activity级别

您还可以控制每个activity是否开启硬件加速,只需在activity元素中添加android:hardwareAccelerated属性即可办到。比如下面的例子,在application级别开启硬件加速,但在某个activity上关闭硬件加速。

<application android:hardwareAccelerated="true">    <activity ... />    <activity android:hardwareAccelerated="false" /></application>

Window级别

如果您需要更小粒度的控制,可以使用如下代码开启某个window的硬件加速:

getWindow().setFlags(    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

注:目前还不能在window级别关闭硬件加速。

View级别

您可以在运行时用以下的代码关闭单个view的硬件加速:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

注:当前你不能在View级别启用硬加速.View层有除禁止硬加速之外的其它功能.

判定一个View是否能被硬加速

  有时一个应用了解是否启用了硬件速是很有用的,对那些自定义View之类的东西尤其重要.在你的应用做了一些不被最新的管线所支持的自定义绘制时这更加重要.

有两种方法可以检查应用是否被硬加速:

View.isHardwareAccelerated():如果View附加到一个硬加速的window上就返回true.

Canvas.isHardwareAccelerated():如果Canvas被硬加速了就返回true.

 

       如果你必须在你的绘制代码中做这个,应使用Canvas.isHardwareAccelerated()而不是View.isHardwareAccelerated().当一个view附加到一个硬加速的window上,它仍可以使用非硬件速的Canvas进行绘制操作.比如当为了高速缓存而把一个view画到一个bitmap中.

为什么需要这么多级别的控制?

很明显,硬件加速能够带来性能提升,android为什么要弄出这么多级别的控制,而不是默认就是全部硬件加速呢?原因是并非所有的2D绘图操作支持硬件加速,如果您的程序中使用了自定义视图或者绘图调用,程序可能会工作不正常。如果您的程序中只是用了标准的视图和Drawable,放心大胆的开启硬件加速吧!具体是哪些绘图操作不支持硬件加速呢:

Canvas
clipPath()
clipRegion()
drawPicture()
drawPosText()
drawTextOnPath()
drawVertices()

Paint
setLinearText()
setMaskFilter()
setRasterizer()

另外还有一些绘图操作,开启和不开启硬件加速,效果不一样:

Canvas
clipRect()
XOR
,
Difference和ReverseDifference裁剪模式被忽略,3D变换将不会应用在裁剪的矩形上。

drawBitmapMesh():colors数组被忽略
drawLines():反锯齿不支持
setDrawFilter():可以设置,但无效果

Paint
setDither(): 忽略
setFilterBitmap():过滤永远开启
setShadowLayer():只能用在文本上

ComposeShader
ComposeShader只能包含不同类型的shader
ComposeShader不能包含ComposeShader

Android的绘制模型

开启硬件加速后,Android框架将采用新的绘制模型。基于软件的绘制模型和基于硬件的绘制模型有和不同呢?

基于软件的绘制模型

在软件绘制模型下,视图按照如下两个步骤绘制:

1. Invalidate the hierarchy(注:hierarchy怎么翻译?)

2. Draw the hierarchy

应用程序调用invalidate()更新UI的某一部分,失效(invalidation)消息将会在整个视图层中传递,计算每个需要重绘的区域(即脏区域)。然后Android系统将会重绘所有和脏区域有交集的view。很明显,这种绘图模式存在缺点:

1. 每个绘制操作中会执行不必要的代码。比如如果应用程序调用invalidate()重绘button,而button又位于另一个view之上,即使该view没有变化,也会进行重绘。

2. 可能会掩盖一些应用程序的bug。因为android系统会重绘与脏区域有交集的view,所以view的内容可能会在没有调用invalidate()的情况下重绘。这可能会导致一个view依赖于其它view的失效才得到正确的行为。

基于硬件的绘制模型

Android系统仍然使用invalidate()和draw()来绘制view,但在处理绘制上有所不同。Android系统记录绘制命令到显示列表,而不是立即执行绘制命令。另一个优化就是Android系统只需记录和更新标记为脏(通过invalidate())的view。新的绘制模型包含三个步骤:

1. Invalidate the hierarchy

2. 记录和更新显示列表

3. 绘制显示列表

转载时请注明出处和作者联系方式:
Android中的硬件加速 mogoweb@gmail.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android硬件加速