Android 使用帧动画内存溢出解决方案

Android 使用帧动画内存溢出解决方案,第1张

概述Android使用帧动画内存溢出解决方案最近在项目遇到的动画效果不好实现,就让UI切成图,采用帧动画实现效果,但是在使用animation-list时,图片也就11张,每张图片大概560k左右,结果内存溢出,崩溃了,自己用了三张

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 使用帧动画内存溢出解决方案所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1147405.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存