android播放帧动画OOM问题解决

时间:2022-08-16 20:52:47

        近来在写项目时,有遇到使用android原生的序列帧动画时,在部分手机(尤其是内存小的)上出现了OOM问题,这种问题是不可避免的。1.我觉首先你要看看是否有适配问题,因为你选择播放的图片要是没有放入对应的适配drawable文件夹,也会出现OOM问题。别说是连播图片了,就连普通的背景切换都有这种风险。2.要是上述没问题,那么就要换思路了。在网上看别人的解决方法,发现了一种好的方法,利用Handle原理来实现图片快速切换效果,这种方法我用到现在还没有一次OOM过,这我也是借鉴别人的。不BB了,上代码。

       写的时候最好在外面套一个try(  ) { }catch( OutOfMemoryError e){  System.gc(); } 通过catch去捕捉OOM异常,然后通知gc去回收。其实android里面调用gc并不能马上进行回收,但我觉得这样DoubleAandroid播放帧动画OOM问题解决dopting (看过片的都知道)。

         新建一个类SceneAnimation:

         

<span style="font-size:18px;">public class SceneAnimation
{
//传入的关联动画的imageView对象(这里不一定是ImageView也可以是其他)
private ImageView mImageView;

//图片数组对象
private int[] mFrameRess;

//每张图片的动画时长(其长度与图片数组对应,用于设置不同时间间隔)
private int[] mDurations;

//每张图片相同的时长
private int mDuration;

 //播放至最后一张图片的下标
private int mLastFrameNo;

private long mBreakDelay;

private int mCode;

public SceneAnimation(Activity activity, ImageView pImageView, int[] pFrameRess, int[] pDurations)
{
IntentActivity = activity;
mImageView = pImageView;
mFrameRess = pFrameRess;
mDurations = pDurations;
mLastFrameNo = pFrameRess.length - 1;

mImageView.setBackgroundResource(mFrameRess[0]);
play(1);
}

public SceneAnimation(ImageView pImageView, int[] pFrameRess, int pDuration)
{
mImageView = pImageView;
mFrameRess = pFrameRess;
mDuration = pDuration;
mLastFrameNo = pFrameRess.length - 1;

mImageView.setBackgroundResource(mFrameRess[0]);
playConstant(1);
}

public SceneAnimation(ImageView pImageView, int[] pFrameRess, int pDuration, int code)
{
mImageView = pImageView;
mFrameRess = pFrameRess;
mDuration = pDuration;
mLastFrameNo = pFrameRess.length - 1;
mCode = code;
mImageView.setBackgroundResource(mFrameRess[0]);
playConstantCode(1);
}

public SceneAnimation(ImageView pImageView, int[] pFrameRess, int pDuration, long pBreakDelay)
{
mImageView = pImageView;
mFrameRess = pFrameRess;
mDuration = pDuration;
mLastFrameNo = pFrameRess.length - 1;
mBreakDelay = pBreakDelay;

mImageView.setBackgroundResource(mFrameRess[0]);
playConstant(1);
}

private void play(final int pFrameNo)
{
mImageView.postDelayed(new Runnable()
{
public void run()
{
mImageView.setBackgroundResource(mFrameRess[pFrameNo]);
// 当播放完成后
if (pFrameNo == mLastFrameNo)
{
// play(0);


}
else
{

play(pFrameNo + 1);
}
}
}, mDurations[pFrameNo]);
}

private void playConstant(final int pFrameNo)
{
mImageView.postDelayed(new Runnable()
{
public void run()
{
mImageView.setBackgroundResource(mFrameRess[pFrameNo]);

if (pFrameNo == mLastFrameNo)
{
// 当动画执行完成后设置imageView可点击
mImageView.setClickable(true);

//播放完成后显示第一张图片
mImageView.setBackgroundResource(mFrameRess[0]);

}
else
{
// 在动画执行时imageView不可点击
mImageView.setClickable(false);
playConstant(pFrameNo + 1);
}
}
}, pFrameNo == mLastFrameNo && mBreakDelay > 0 ? mBreakDelay : mDuration);
}

private void playConstantCode(final int pFrameNo)
{
mImageView.postDelayed(new Runnable()
{
public void run()
{
mImageView.setBackgroundResource(mFrameRess[pFrameNo]);

if (pFrameNo == mLastFrameNo)
{
// 当动画执行完成后设置imageView可点击
mImageView.setClickable(true);
mImageView.setBackgroundResource(mFrameRess[0]);
}
else
{
// 在动画执行时imageView不可点击
mImageView.setClickable(false);
playConstantCode(pFrameNo + 1);
}
}
}, pFrameNo == mLastFrameNo && mBreakDelay > 0 ? mBreakDelay : mDuration);
}
};</span>


         上述代码是我在网上借鉴别人的,至不过是优化和添加些注释。我觉得这样差不多可以解决图片频繁轮换OOM问题。要是能根据屏幕的宽高动态设置Bitmap对象大小这样更好

 <span style="font-size:18px;"> ImageView.setImageBitmap(ImageUtils.decodeSampledBitmapFromResource(getResources(),
ImageViewRes[position],width,height));</span>


          还有就是我记得Xutils中也有关于图片加载方法,

          BitmapUtils bitmapUtils = new BitmapUtils(this);

// 加载网络图片
bitmapUtils.display(testImageView, "http://bbs.lidroid.com/static/image/common/logo.png");

// 加载本地图片(路径以/开头, 绝对路径)
bitmapUtils.display(testImageView, "/sdcard/test.jpg");

// 加载assets中的图片(路径以assets开头)
bitmapUtils.display(testImageView, "assets/img/wallpaper.jpg");
        不过我个人不喜欢Xutils框架,耦合性太高,扩展性不强,毕竟扶着拐杖是走不远的,还是volley好用(个人观点)