Android硬件加速 问题和错误

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wenbitianxiafeng/article/details/19974851

问题

在Android 4.0的某些设备上,在View刷新时会出现花屏和屏幕上的某些View错位的现象。 经过调查后发现adb logcat中出现很多OpenGLRenderer: 0x501的错位:

1
2
3
09-18 14:34:39.090: DEBUG/OpenGLRenderer(3104): GL error from OpenGLRenderer: 0x501
09-18 14:34:39.386: DEBUG/OpenGLRenderer(3104): GL error from OpenGLRenderer: 0x501
09-18 14:34:39.656: DEBUG/OpenGLRenderer(3104): GL error from OpenGLRenderer: 0x501

从这个日志,初步怀疑是硬件加速导致的问题。 经过分析发现使用了比较复杂的自定义View,可能会导致硬件加速渲染出错。

硬件加速的优点与缺点

硬件加速能使用GPU来加速2D图像的渲染速度,但是硬件加速并不能完全支持所有的渲染操作, 针对自定义的View,硬件加速可能导致渲染出现错误。 如果有自定义的View,需要在硬件加速的设备上进行测试,如果出现渲染的问题,需要关闭硬件加速。

开启和关闭硬件加速

对硬件加速的开关可以在不同的级别进行控制:

  • Application
  • Activity
  • Windows
  • View

Application级别

在Applciation级别控制硬件加速的开关:

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

Activity级别

可以对单个的Activity控制是否启用硬件加速:

1
2
3
4
<application android:hardwareAccelerated="true">
    <activity ... />
    <activity android:hardwareAccelerated="false" />
</application>

Window级别

1
2
3
getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

View级别

在指定的View上关闭硬件加速:

1
myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

或者使用android:layerType="software"来关闭硬件加速:

1
2
3
4
5
6
7
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:paddingLeft="2dp"
    android:layerType="software"
    android:paddingRight="2dp" >

如何判断一个View是否启用了硬件加速

  • View.isHardwareAccelerated() returns true if the View is attached to a hardware accelerated window.
  • Canvas.isHardwareAccelerated() returns true if the Canvas is hardware accelerated

Android Drawing Models

When hardware acceleration is enabled, the Android framework utilizes a new drawing model that utilizes display lists to render your application to the screen. To fully understand display lists and how they might affect your application, it is useful to understand how Android draws views without hardware acceleration as well. The following sections describe the software-based and hardware-accelerated drawing models.

Software-based drawing model

In the software drawing model, views are drawn with the following two steps:

  1. Invalidate the hierarchy
  2. Draw the hierarchy

Whenever an application needs to update a part of its UI, it invokes invalidate() (or one of its variants) on any view that has changed content. The invalidation messages are propagated all the way up the view hierarchy to compute the regions of the screen that need to be redrawn (the dirty region). The Android system then draws any view in the hierarchy that intersects with the dirty region. Unfortunately, there are two drawbacks to this drawing model:

  • First, this model requires execution of a lot of code on every draw pass. For example, if your application calls invalidate() on a button and that button sits on top of another view, the Android system redraws the view even though it hasn’t changed.
  • The second issue is that the drawing model can hide bugs in your application. Since the Android system redraws views when they intersect the dirty region, a view whose content you changed might be redrawn even though invalidate() was not called on it. When this happens, you are relying on another view being invalidated to obtain the proper behavior. This behavior can change every time you modify your application. Because of this, you should always call invalidate() on your custom views whenever you modify data or state that affects the view’s drawing code.

Note: Android views automatically call invalidate() when their properties change, such as the background color or the text in a TextView.

Hardware accelerated drawing model

The Android system still uses invalidate() and draw() to request screen updates and to render views, but handles the actual drawing differently. Instead of executing the drawing commands immediately, the Android system records them inside display lists, which contain the output of the view hierarchy’s drawing code. Another optimization is that the Android system only needs to record and update display lists for views marked dirty by an invalidate() call. Views that have not been invalidated can be redrawn simply by re-issuing the previously recorded display list. The new drawing model contains three stages:

  1. Invalidate the hierarchy
  2. Record and update display lists
  3. Draw the display lists

With this model, you cannot rely on a view intersecting the dirty region to have its draw() method executed. To ensure that the Android system records a view’s display list, you must call invalidate(). Forgetting to do so causes a view to look the same even after changing it, which is an easier bug to find if it happens.

Using display lists also benefits animation performance because setting specific properties, such as alpha or rotation, does not require invalidating the targeted view (it is done automatically). This optimization also applies to views with display lists (any view when your application is hardware accelerated.) For example, assume there is a LinearLayout that contains a ListView above a Button. The display list for the LinearLayout looks like this:

  • DrawDisplayList(ListView)
  • DrawDisplayList(Button)

Assume now that you want to change the ListView’s opacity. After invoking setAlpha(0.5f) on the ListView, the display list now contains this:

  • SaveLayerAlpha(0.5)
  • DrawDisplayList(ListView)
  • Restore
  • DrawDisplayList(Button)

The complex drawing code of ListView was not executed. Instead, the system only updated the display list of the much simpler LinearLayout. In an application without hardware acceleration enabled, the drawing code of both the list and its parent are executed again.

参考



最近做的程序中遇到了一些奇怪的问题:来源未知,只对特定机型出现问题。如果你也遇到了,可以考虑是不是硬件加速(Hardware Acceleration)的错

从Android3.0 (API level 11)开始,Android的2D显示管道被被设计得更加支持硬加速了.硬加速使用GPU承担了所有在View的canvas上执行的绘制操作。

硬件加速是个好东西,可以让ListView、WebView滑动的更流畅,但是也总是会出现莫名其妙的的问题。

问题1:EditText中文字的重叠


这是我之前一个博客中解决过的问题,详见:http://blog.csdn.net/icyfox_bupt/article/details/12837093

在某些4.x的机器中,如果打开了硬件加速,EditText会出现奇怪的文字重叠的情况。



解决的方法:对EditText关闭硬件加速即可。


问题2:图片无法显示

做的程序里有的时候会需要加载大图,但是硬件加速中 OpenGL对于内存是有限制的。如果遇到了这个限制,LogCat只会报一个Warning: Bitmap too large to be uploaded into a texture (587x7696, max=2048x2048)


这时我们就需要把硬件加速关闭了。

但开始我是这样处理的,我关闭了整个应用的硬件加速:

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <application  
  2.     android:allowBackup="true"  
  3.     android:icon="@drawable/ic_launcher"  
  4.     android:hardwareAccelerated="false"  
  5.     android:label="@string/app_name"  
  6.     android:theme="@style/AppTheme" >  

随后我就发现,虽然图片可以显示了,但是ListView和WebView等控件显得特别的卡,这说明硬件加速对于程序的性能提升是很明显的。所以我就改为对于Activity的关闭

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <activity  
  2.     android:name="icyfox.webviewimagezoomertest.MainActivity"  
  3.     android:label="@string/app_name"  
  4.     android:hardwareAccelerated="false"  
这样问题得到了较好的解决,实际上,我们还可以对每个控件是否加速进行控制。

展开阅读全文

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