AndroID 使用帧动画内存溢出解决方案
最近在项目遇到的动画效果不好实现,就让UI切成图,采用帧动画实现效果,但是在使用animation-List时,图片也就11张,每张图片大概560k左右,结果内存溢出,崩溃 了,自己用了三张都崩溃;拿代码说;
1.anin_searh.xml
<?xml version="1.0" enCoding="utf-8"?> <animation-List xmlns:androID="http://schemas.androID.com/apk/res/androID" androID:oneshot="true"> <item androID:drawable="@drawable/a1" androID:duration="100"></item> <item androID:drawable="@drawable/a2" androID:duration="100"></item> <item androID:drawable="@drawable/a4" androID:duration="100"></item> <item androID:drawable="@drawable/a5" androID:duration="100"></item> <item androID:drawable="@drawable/a6" androID:duration="100"></item> <item androID:drawable="@drawable/a7" androID:duration="100"></item> <item androID:drawable="@drawable/a8" androID:duration="100"></item> <item androID:drawable="@drawable/a9" androID:duration="100"></item> <item androID:drawable="@drawable/a10" androID:duration="100"></item> <item androID:drawable="@drawable/a11" androID:duration="100"></item> </animation-List>
2.使用帧动画
search_scale_iv.setBackgroundResource(R.drawable.anim_search); AnimationDrawable drawable = (AnimationDrawable) search_scale_iv.getBackground(); drawable.start();
结果setBackgroundResource出现内存溢出,这个方法其实获取drawable时候,会消耗很多内存,很容易内存溢出,崩溃。
3.解决方法:在网上找了个类,处理,结果我使用11张560k大小图片,没有内存溢出;
import androID.content.Context; import androID.content.res.XmlResourceParser; import androID.graphics.BitmapFactory; import androID.graphics.drawable.AnimationDrawable; import androID.graphics.drawable.BitmapDrawable; import androID.graphics.drawable.Drawable; import androID.os.Handler; import androID.Widget.ImageVIEw; import org.apache.commons.io.IoUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.List; /**** * 此工具类源于stack over flow * 原文链接:http://stackoverflow.com/questions/8692328/causing-outofmemoryerror-in-frame-by-frame-animation-in-androID * 主要使用了BitmapFactory.decodeByteArray方法通过底层C来绘制图片,有效防止OOM * 使用了第三方类库:org.apache.commons.io.IoUtils,将inputstream转为byte字节数组 * *******/ public class MyAnimationDrawable { public static class MyFrame { byte[] bytes; int duration; Drawable drawable; boolean isReady = false; } public interface OnDrawableLoadedListener { public voID onDrawableLoaded(List<MyFrame> myFrames); } // 1 /*** * 性能更优 * 在animation-List中设置时间 * **/ public static voID animaterawManuallyFromXML(int resourceID,final ImageVIEw imageVIEw,final Runnable onStart,final Runnable onComplete) { loadRaw(resourceID,imageVIEw.getContext(),new OnDrawableLoadedListener() { @OverrIDe public voID onDrawableLoaded(List<MyFrame> myFrames) { if (onStart != null) { onStart.run(); } animaterawManually(myFrames,imageVIEw,onComplete); } }); } // 2 private static voID loadRaw(final int resourceID,final Context context,final OnDrawableLoadedListener onDrawableLoadedListener) { loadFromXml(resourceID,context,onDrawableLoadedListener); } // 3 private static voID loadFromXml(final int resourceID,final OnDrawableLoadedListener onDrawableLoadedListener) { new Thread(new Runnable() { @OverrIDe public voID run() { final ArrayList<MyFrame> myFrames = new ArrayList<MyFrame>(); XmlResourceParser parser = context.getResources().getXml( resourceID); try { int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_document) { if (eventType == XmlPullParser.START_document) { } else if (eventType == XmlPullParser.START_TAG) { if (parser.getname().equals("item")) { byte[] bytes = null; int duration = 1000; for (int i = 0; i < parser.getAttributeCount(); i++) { if (parser.getAttributename(i).equals( "drawable")) { int resID = Integer.parseInt(parser .getAttributeValue(i) .substring(1)); bytes = IoUtils.toByteArray(context .getResources() .openRawResource(resID)); } else if (parser.getAttributename(i) .equals("duration")) { duration = parser.getAttributeIntValue( i,1000); } } MyFrame myFrame = new MyFrame(); myFrame.bytes = bytes; myFrame.duration = duration; myFrames.add(myFrame); } } else if (eventType == XmlPullParser.END_TAG) { } else if (eventType == XmlPullParser.TEXT) { } eventType = parser.next(); } } catch (IOException e) { e.printstacktrace(); } catch (XmlPullParserException e2) { // Todo: handle exception e2.printstacktrace(); } // Run on UI Thread new Handler(context.getMainLooper()).post(new Runnable() { @OverrIDe public voID run() { if (onDrawableLoadedListener != null) { onDrawableLoadedListener.onDrawableLoaded(myFrames); } } }); } }).run(); } // 4 private static voID animaterawManually(List<MyFrame> myFrames,ImageVIEw imageVIEw,Runnable onComplete) { animaterawManually(myFrames,onComplete,0); } // 5 private static voID animaterawManually(final List<MyFrame> myFrames,final Runnable onComplete,final int frameNumber) { final MyFrame thisFrame = myFrames.get(frameNumber); if (frameNumber == 0) { thisFrame.drawable = new BitmapDrawable(imageVIEw.getContext() .getResources(),BitmapFactory.decodeByteArray( thisFrame.bytes,thisFrame.bytes.length)); } else { MyFrame prevIoUsFrame = myFrames.get(frameNumber - 1); ((BitmapDrawable) prevIoUsFrame.drawable).getBitmap().recycle(); prevIoUsFrame.drawable = null; prevIoUsFrame.isReady = false; } imageVIEw.setimageDrawable(thisFrame.drawable); new Handler().postDelayed(new Runnable() { @OverrIDe public voID run() { // Make sure ImageVIEw hasn't been changed to a different Image // in this time if (imageVIEw.getDrawable() == thisFrame.drawable) { if (frameNumber + 1 < myFrames.size()) { MyFrame nextFrame = myFrames.get(frameNumber + 1); if (nextFrame.isReady) { // Animate next frame animaterawManually(myFrames,frameNumber + 1); } else { nextFrame.isReady = true; } } else { if (onComplete != null) { onComplete.run(); } } } } },thisFrame.duration); // Load next frame if (frameNumber + 1 < myFrames.size()) { new Thread(new Runnable() { @OverrIDe public voID run() { MyFrame nextFrame = myFrames.get(frameNumber + 1); nextFrame.drawable = new BitmapDrawable(imageVIEw .getContext().getResources(),BitmapFactory.decodeByteArray(nextFrame.bytes,nextFrame.bytes.length)); if (nextFrame.isReady) { // Animate next frame animaterawManually(myFrames,frameNumber + 1); } else { nextFrame.isReady = true; } } }).run(); } } //第二种方法 /*** * 代码中控制时间,但不精确 * duration = 1000; * ****/ public static voID animateManuallyFromrawResource( int animationDrawableResourceID,Runnable onStart,Runnable onComplete,int duration) throws IOException,XmlPullParserException { AnimationDrawable animationDrawable = new AnimationDrawable(); XmlResourceParser parser = imageVIEw.getContext().getResources() .getXml(animationDrawableResourceID); int eventType = parser.getEventType(); while (eventType != XmlPullParser.END_document) { if (eventType == XmlPullParser.START_document) { } else if (eventType == XmlPullParser.START_TAG) { if (parser.getname().equals("item")) { Drawable drawable = null; for (int i = 0; i < parser.getAttributeCount(); i++) { if (parser.getAttributename(i).equals("drawable")) { int resID = Integer.parseInt(parser .getAttributeValue(i).substring(1)); byte[] bytes = IoUtils.toByteArray(imageVIEw .getContext().getResources() .openRawResource(resID));//IoUtils.readBytes drawable = new BitmapDrawable(imageVIEw .getContext().getResources(),BitmapFactory.decodeByteArray(bytes,bytes.length)); } else if (parser.getAttributename(i) .equals("duration")) { duration = parser.getAttributeIntValue(i,66); } } animationDrawable.addFrame(drawable,duration); } } else if (eventType == XmlPullParser.END_TAG) { } else if (eventType == XmlPullParser.TEXT) { } eventType = parser.next(); } if (onStart != null) { onStart.run(); } animateDrawableManually(animationDrawable,0); } private static voID animateDrawableManually( final AnimationDrawable animationDrawable,final int frameNumber) { final Drawable frame = animationDrawable.getFrame(frameNumber); imageVIEw.setimageDrawable(frame); new Handler().postDelayed(new Runnable() { @OverrIDe public voID run() { // Make sure ImageVIEw hasn't been changed to a different Image // in this time if (imageVIEw.getDrawable() == frame) { if (frameNumber + 1 < animationDrawable.getNumberOfFrames()) { // Animate next frame animateDrawableManually(animationDrawable,frameNumber + 1); } else { // Animation complete if (onComplete != null) { onComplete.run(); } } } } },animationDrawable.getDuration(frameNumber)); } }
这里需要导入jar,
import org.apache.commons.io.IoUtils;
4.然后通过上述类,来调用自己的动画xml,
MyAnimationDrawable.animaterawManuallyFromXML(R.drawable.anim_search,search_scale_iv,new Runnable() { @OverrIDe public voID run() { // Todo onStart // 动画开始时回调 log.d("","start"); } },new Runnable() { @OverrIDe public voID run() { // Todo onComplete // 动画结束时回调 log.d("","end"); } });
这样在使用帧动画时,可以有效的适度防止内存溢出,谁还有什么办法,欢迎交流!
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
总结以上是内存溢出为你收集整理的Android 使用帧动画内存溢出解决方案全部内容,希望文章能够帮你解决Android 使用帧动画内存溢出解决方案所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)