彭思正的博客

耐得住寂寞,经的起诱惑,守得住繁华,才能得到辉煌

java.lang.IllegalStateException: Hardware acceleration can only be used with a single UI thread.

今天在研究一个东西的时候有的真机上报这个错误 (我发现的是自己的coopal的4.4手机上),

这种情况是由于硬件加速的原因引起的

but 我在manifest中已经关闭了硬件加速,代码如下

 <application
        android:allowBackup="true"
        android:hardwareAccelerated="false"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >。。。。。。。。。。。

这个对大部分手机ok的         然而coopal的4.4手并没有多大作用,程序依旧惨死

后来上网搜了下,简单暴力的做法是

开发者模式中“强制使用GPU渲染”的选项开启了,关闭应该就不会开启硬件加速了。

既然都扯到硬件加速了,索性就来了解一下硬件加速吧  


从Android3.0(API Level 11)开始,Android 2D渲染管道能够更好的支持硬件加速。硬件加速执行的所有的绘图操作都是使用GPU在View对象的画布上来进行的。因为启用硬件加速会增加资源的需求,因此这样的应用会占用更多的内存。

硬件加速在target api大于等于14的情况下,是默认开启的,但是我们也可以显示的开启硬件加速。如果应用程序只使用标准的View和Drawable,那么打开全局硬件加速不会导致任何不良的绘制影响。然而,由于硬件加速并不支持所有的2D图形绘制操作,因此对于那些使用定制的View和绘制调用来说,打开全局硬件加速,会造成影响。对于这个问题,通常是对那些不可见的元素进行了异常或错误的像素渲染。为了避免这种问题,Android提供了多个级别的硬件加速操作(开启或者关闭),具体可见控制硬件加速。

这里⚠️ :如果应用程序执行了定制化的绘图,并且开启了硬件加速,那么就要在带有硬件加速的真机上测试,以便发现问题。 不支持的绘制操作描述了硬件加速的问题,以及如何解决它们。


四个级别的   硬件加速

1)application(app的加速)

在应用的Android清单文件中,把下列属性添加到元素中,能够开启整个应用程序的硬件加速:如下

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

2)activity(界面的加速)

如果应用程序不能正确的使用被打开的全局硬件加速,那么也可以在Activity级别上进行控制。在元素中使用android:hardwareAccelerated属性,能够启用或禁止Activity级别的硬件加速。以下示例启用全局的硬件加速,但却禁止了一个Activity的硬件加速:    同上面一样,在AndroidManifest中  
<span style="font-size:14px;"><application android:hardwareAccelerated="true">
    <activity ... />
    <activity android:hardwareAccelerated="false" />
</application></span>

3)Window 窗口

如果需要更精细的控制,就可以使用下列代码来针对给定的Window来启用硬件加速
getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

4)View级别

在运行时,可以针对一个独立的View对象使用下列代码来禁止硬件加速:
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

这里要注意的是:Window和View级别只能关闭硬件加速,而不能控制开启

判断一个view是否被硬件加速

使用情况 :

有些时候,知道当前的View对象(尤其是那些定制的View对象)是否被硬件加速对应用程序来说是非常有用的。如果应用程序做了很多定制的绘图操作,并且不是所有的操作都会被新的渲染管道所支持,那么这种判断就特别有用。

有两种不同的方法来检查应用程序是否被硬件加速了:

View.isHardwareAccelerated():返回值为true,View对象跟一个被硬件加速的窗口绑定;反之,未加速
Canvas.isHardwareAccelerated():返回值为true,Canvas对象被硬件加速;反之,未加速
建议的话使用:因为View关联到一个硬件加速的window上,任然可以使用非硬件加速的canvas绘制。


View layers 

所有的Android版本View都可以在非屏幕内存(off-screen buffers)上渲染,使用view的drawing cache或者Canvas.saveLayer().非屏幕内存或者layers有许多用处,在对复杂对View做动画或者做一些叠加复合效果时可以得到更好的性能。 
在Android3.0之后可以使用View.setLayerType()来控制如何使用layers。

LAYER_TYPE_NONE: 默认行为,正常渲染,不会在off-screen buffer上备份

  LAYER_TYPE_HARDWARE :如果应用开启了硬件加速view渲染在硬件上,否则与LAYER_TYPE_SOFTWARE行为一样

LAYER_TYPE_SOFTWARE: 用软件渲染在一个bitmap上

使用硬件加速有更高的效率,如果产生兼容性问题,可以用setLayerType改变渲染方式。

View layers and animations

当应用程序被硬件加速的时候,硬件层能够传递更快、更平滑的动画。当播放具有复杂的绘图操作的动画时,以每秒60帧的速度播放不总是可能的。但是,可以通过使用硬件层把View对象渲染在硬件纹理中,缓解这种情况。硬件纹理能够被用于动画视图,这样在该View对象呈现动画时,就可以消除View对象所需要的重绘操作。除非该View对象的属性发生变化时(invalidate()方法被调用),它才会被重绘。如果在应用程序运行一个动画,并且没有获得想要的平滑结果,就要考虑在动画View上启用硬件层。

当一个View从硬件层被返回时,通过层方法处理的某些属性会被合成到屏幕上。因为它们不需要让View对象失效和重绘,所以设置这些属性是非常高效的。下面列出了影响层被合成的方式。调用这些属性设置器,会导致失效处理的优化,并且不会对目标View对象进行重绘:

alpha:改变层(layer)的透明度;x,y,translation,translation:改变层的位置;scaleX,scaleY:改变层的尺寸;rotation,rotation,rotationY:改变3D空间中层的方向;pivotX,pivotY:改变层的变换起源。

这些属性是在用ObjectAnimator对象给View对象设置动画时所使用的名称。如果想要访问这些属性,就要调用相应的set或get方法。例如,要修改alpha属性,就要调用setAlpha()方法。下面的代码展示了在3D空间中围绕Y轴旋转View对象的最有效的方法:

<span style="font-size:14px;">view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator.ofFloat(view, "rotationY", 180).start();</span>

View.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 180);
animator.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        view.setLayerType(View.LAYER_TYPE_NONE, null);
    }
});
animator.start();




参考:http://blog.csdn.net/xu_fu/article/details/48208795
http://www.2cto.com/kf/201405/299584.html

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013424496/article/details/52995115
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭