之前在做公司项目实现文件上传的时候,遇到过OOM的异常,但是又确实需要这么多的内存。
出现错误:Throwing OutOfMemoryError failed to allocate a *** byte allocation with *** free bytes and ***mb until OOM
看到一篇帖子上提示通过设置关闭硬件加速和开启最大内存,加上以下代码,竟然神奇的好了。
android:hardwareAccelerated="false"
android:largeHeap="true"
可是过去了很多天,发现项目中的播放器无发播放了(有声音没画面),百思不得其解,想来想去,通过版本管理工具查看,好久没动过播放器的代码了,于是抓log日志,最后通过日志分析,播放器没有走硬件直接软件了,设置给播放器的画布Surface是空的,回过头去去查看TextureView的回调监听设置了之后,没有执行回调,这可把我郁闷坏了。
最终通过查看资料发现:TextureView必须工作在硬件加速条件, 否则什么都不执行。
官方文档:
A TextureView can be used to display a content stream. Such a content stream can for instance be a video or an OpenGL scene. The content stream can come from the application’s process as well as a remote process.
TextureView can only be used in a hardware accelerated window. When rendered in software, TextureView will draw nothing.
Unlike SurfaceView , TextureView does not create a separate window but behaves as a regular View. This key difference allows a TextureView to be moved, transformed, animated, etc. For instance, you can make a TextureView semi-translucent by calling myView.setAlpha(0.5f).
Using a TextureView is simple: all you need to do is get its SurfaceTexture . The SurfaceTexture can then be used to render content. The following example demonstrates how to render the camera preview into a TextureView
看重点**“TextureView can only be used in a hardware accelerated window. When rendered in software, TextureView will draw nothing.”**也就是说“TextureView只能在硬件加速窗口中使用。在软件中渲染时,TextureView将不绘制任何内容。”
因此需要 android:hardwareAccelerated=”true”或者 Window w = activity.getWindow(); w.setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
如果是在Service里面,直接在AndroidManifest设置会不起作用,只能直接对Window设置flag
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
1、TextureView是Android 4.0之后加入的,低版本么这个类。TextureView必须工作在开启硬件加速的环境中,也即配置文件里Activity的设置项里:android:hardwareAccelerated=“true” 默认的这个属性就是true,因此不用再写了。但如果写成false,可以看到onSurfaceTextureAvailable()这个回调就进不来了;
2、有两点跟Surfaceview不同。第一,TextureView创建过程中没有进到onSurfaceTextureSizeChanged()这个函数里。而SurfaceView在创建过程中,从无到有的时候会进到大小发生变化回调里。第二,onSurfaceTextureUpdated()这个函数每上来一帧数据,这块就进来一次。这是跟Surfaceview相比,最伟大的一个地方。通过这个接口,可以将上来的SurfaceTexture送给OpenGL再去处理。这个回调是实时的,而非用Camera的PreviewCallback这种2次回调的方式。从时间看,基本上每32ms左右上来一帧数据,即每秒30帧,跟本手机的Camera的性能吻合。
3、Camera再执行startPreview时必须保证TextureView的SurfaceTexture上来了,如果因为一些性能原因onSurfaceTextureAvailable()这个回调上不来就开预览,就开不了的。如果发生这种情况,就在onSurfaceTextureAvailable()回调里执行open和startPreview操作,保证万无一失。
4、SurfaceTexture和TextureView的关系:
如果说TextureView是一幅画的话,那SurfaceTexture就是画布,真正渲染的载体是SurfaceTexture。
5、TextureView可以像一般View执行各种变化,其中有个textureView.setAlpha(1.0f);默认不写这句话,它的alpha也是1.0f,即不透明。如果设成透明0.0f,可以看到啥都看不到了,这一点跟Surfaceview刚好相反。Surfaceview的SurfaceHolder一般要设一下Transparent即透明。但TextureView因为是个view,任何一个png的照片透明度设成0肯定啥都看不到。
6、如果认为预览个Camera这就是TextureView和SurfaceTexture的使命的话,就大错特错了,真正用意是和OpenGL无缝连接。