Android 帧动画OOM问题优化
来源:互联网 发布:飞鱼网络电视1.3.8 编辑:程序博客网 时间:2024/05/16 11:07
转载请注明出处,谢谢
- 普通实现
实现一个帧动画,最先想到的就是用animation-list将全部图片按顺序放入,并设置时间间隔和播放模式。然后将该drawable设置给ImageView或Progressbar就OK了。
首先创建帧动画资源文件drawable/anim.xml,oneshot=false为循环播放模式,ture为单次播放;duration为每帧时间间隔,单位毫秒。
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false" > <item android:drawable="@drawable/img0" android:duration="17" /> <item android:drawable="@drawable/img1" android:duration="17" /> <item android:drawable="@drawable/img2" android:duration="17" /></animation-list>
然后在代码中找到播放该动画的ImageView,将资源赋给该控件就可以控制动画开始与结束了,是不是超简单。
AnimationDrawable animationDrawable;if (imageView.getDrawable() == null) { imageView.setImageResource(R.drawable.loading_anim); animationDrawable = (AnimationDrawable) imageView.getDrawable();}animationDrawable.start();//开始animationDrawable.stop();//结束
- OOM问题及优化
. 内存溢出咋办
用普通方法实现帧动画用到普通场景是没问题的,如果碰到几十甚至几百帧图片,而且每张图片几百K的情况,呵呵。例如,做一个很炫的闪屏帧动画,要保证高清且动作丝滑,就需要至少几十张高清图片。这时,OOM问题就出来了,闪屏进化成了一闪~
别慌,像我这样的菜鸟遇到问题就会找度娘和gayhub,大神们肯定已经有解决方案了。随手一搜就在StackOverflow上找到了解决办法:
http://stackoverflow.com/questions/8692328/causing-outofmemoryerror-in-frame-by-frame-animation-in-android
. 解决思路
先分析下普通方法为啥会OOM,从xml中读取到图片id列表后就去硬盘中找这些图片资源,将图片全部读出来后按顺序设置给ImageView,利用视觉暂留效果实现了动画。一次拿出这么多图片,而系统都是以Bitmap位图形式读取的(作为OOM的常客,这锅Bitmap来背);而动画的播放是按顺序来的,大量Bitmap就排好队等待播放然后释放,然而这个排队的地方只有10平米,呵呵~发现问题了吧。
按照大神的思路,既然来这么多Bitmap,一次却只能临幸一个,那么就翻牌子吧,轮到谁就派个线程去叫谁,bitmap1叫到了得叫上下一位bitmap2做准备,这样更迭效率高一些。为了避免某个bitmap已被叫走了线程白跑一趟的情况,加个Synchronized同步下数据信息,实现代码如下:
public synchronized void start() { mShouldRun = true; if (mIsRunning) return; Runnable runnable = new Runnable() { @Override public void run() { ImageView imageView = mSoftReferenceImageView.get(); if (!mShouldRun || imageView == null) { mIsRunning = false; if (mOnAnimationStoppedListener != null) { mOnAnimationStoppedListener.AnimationStopped(); } return; } mIsRunning = true; //新开线程去读下一帧 mHandler.postDelayed(this, mDelayMillis); if (imageView.isShown()) { int imageRes = getNext(); if (mBitmap != null) { // so Build.VERSION.SDK_INT >= 11 Bitmap bitmap = null; try { bitmap = BitmapFactory.decodeResource(imageView.getResources(), imageRes, mBitmapOptions); } catch (Exception e) { e.printStackTrace(); } if (bitmap != null) { imageView.setImageBitmap(bitmap); } else { imageView.setImageResource(imageRes); mBitmap.recycle(); mBitmap = null; } } else { imageView.setImageResource(imageRes); } } } }; mHandler.post(runnable); }
. 进一步优化
为了快速读取SD卡中的图片资源,这里用到了Apache的IOUtils。在位图处理上使用了BitmapFactory.Options()相关设置,InBitmap,当图片大小类型相同时,虚拟机就对位图进行内存复用,不再分配新的内存,可以避免不必要的内存分配及GC。
if (Build.VERSION.SDK_INT >= 11) { Bitmap bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap(); int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap.Config config = bmp.getConfig(); mBitmap = Bitmap.createBitmap(width, height, config); mBitmapOptions = new BitmapFactory.Options(); //设置Bitmap内存复用 mBitmapOptions.inBitmap = mBitmap;//Bitmap复用内存块 mBitmapOptions.inMutable = true;//解码时返回可变Bitmap mBitmapOptions.inSampleSize = 1;//缩放比例 }
- 实现过程
将大神的代码整理搬运后,整合成demo到自己GitHub上,具体项目请移步
https://github.com/VDshixiaoming/AnimationTest
使用很简单:
/** * 将帧动画资源id以字符串数组形式写到values/arrays.xml中 * FPS为每秒播放帧数,FPS = 1/T,(T--每帧间隔时间秒) */AnimationsContainer.FramesSequenceAnimation animation = AnimationsContainer.getInstance(R.array.XXX, FPS).createProgressDialogAnim(imageView);animation.start();//动画开始animation.stop();//动画结束
注意图片资源ID需要以String数组形式放入xml中,然后再利用TypedArray将字符串转为资源ID。如果直接用@drawable/img1这样的形式放入Int数组中,是没法读取到正真的资源ID的。
从xml中读取资源ID数组代码:
/** * 从xml中读取帧数组 * @param resId * @return */ private int[] getData(int resId){ TypedArray array = mContext.getResources().obtainTypedArray(resId); int len = array.length(); int[] intArray = new int[array.length()]; for(int i = 0; i < len; i++){ intArray[i] = array.getResourceId(i, 0); } array.recycle(); return intArray; }
- 实现效果
实现完了当然迫不及待的到真机上跑跑,测下效果。
看图说话,这么明显的坎儿就是应为一次读取图片造成的,分分钟OOM的节奏。再看看优化后的结果:
是不是很养眼,不过最前面刚进界面时的蜜汁GC我还没弄清除~~
最后奉上动图效果,是不是非常丝滑酸爽
Demo地址:
https://github.com/VDshixiaoming/AnimationTest
- Android 帧动画OOM问题优化
- Android帧动画OOM
- Android 用surfaceview模拟帧动画的效果,解决帧动画的OOM问题
- Android 逐帧动画oom解决办法
- android播放帧动画OOM问题解决
- Android 逐帧动画OOM的解决方法
- 【Android】Android优化-oom
- Android OOM优化
- Android内存优化 OOM
- Android内存优化--OOM
- OOM问题优化问题总结
- android帧动画太多太卡(OOM)解决方案
- android OOM问题经验
- Android OOM问题排查
- Android OOM 问题整理
- Android 内存优化解决方案 (OOM)
- Android内存优化之OOM
- Android内存优化之OOM
- 在 iOS 模拟器中调试 Web 页面
- 关于返回上一级视图后视图中tableview内容不刷新的问题
- android适配
- webform后台指定ddl的默认值
- webstorm vue-cli的热加载好像失灵了·····
- Android 帧动画OOM问题优化
- BZOJ 1251 序列终结者
- Bootstrap3 表单-输入框焦点-被禁用的输入框
- ADB常用命令
- struts学习(一)
- C++ restrict
- 关于OBJC的静态变量
- linux 4 -awk
- Java性能优化之 导致系统瓶颈的计算资源