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

原创 2016年11月01日 15:04:23

今天在研究一个东西的时候有的真机上报这个错误 (我发现的是自己的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();



更多请看:https://developer.android.com/guide/topics/graphics/hardware-accel.html#determining

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Hardware acceleration can only be used with a single UI thread.

Hardware acceleration can only be used with a single UI thread.

android编译错误之“Hardware acceleration can only be used with a single UI thread”,硬件加速

今天在调试的时候碰到一个问题,在处理对话框点击完button使其消失的过程中,报错如下: java.lang.IllegalStateException: Hardware acceleration...

Android Window 二 可移动悬浮窗口 WindowManager

一、有图有真相 二、如何创建悬浮窗口      比较简单,主要是使用WindowManager API,以下是使用方法 @Override protected void on...

Android 理解Window 和 WindowManager

这几天阅读了《Android开发艺术探索》的关于Window和WindowManager的章节,特此写一片博文来整理和总结一下学到的知识,做一个笔记方便自己查阅。  说到Window,大家都会想到所...

Android 使用WindowManager实现悬浮窗及源码解析

本文已授权微信公众号《鸿洋》原创首发,转载请务必注明出处。 一个Activity、一个Service和两个布局文件。布局十分简单,这里就不贴了,大概描述下。activity_main.xml中俩按钮,...

安卓学习笔记之理解Window与WindowManager

Window的概念 Window表示的是一个窗口的概念,它是一个抽象类,它的具体实现是PhoneWindow。创建一个Window需要通过WindowManger来完成。WindowManger是外...

java.lang.IllegalStateException: ActionBarContextView can only be used with android:layout_width="

- Steps to reproduce the problem (including sample code if appropriate). Implement a Dialog(Maybe an...
  • hustpzb
  • hustpzb
  • 2011年10月28日 11:50
  • 3517

java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be acce

java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be a...
  • briblue
  • briblue
  • 2016年12月12日 20:06
  • 1159

gerrit注册邮箱500错java.lang.IllegalStateException:Can only invoke this method before calling getInstance

gerrit-2.12.4版本在用户设置邮箱账户时会包500错误,在日志中可以看到java.lang.ExceptionInInitializerError...

解决IE浏览器的only one scriptx object can be used per browser window问题

浏览器:IE   问题:浏览器报only one scriptx object can be used per browser window错误 一般的ScriptX控件的引入需要在当前文件中这样写:...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java.lang.IllegalStateException: Hardware acceleration can only be used with a single UI thread.
举报原因:
原因补充:

(最多只允许输入30个字)