国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android 使用幀動畫內(nèi)存溢出解決方案

2019-12-12 04:12:51
字體:
供稿:網(wǎng)友

Android 使用幀動畫內(nèi)存溢出解決方案

最近在項目遇到的動畫效果不好實現(xiàn),就讓UI切成圖,采用幀動畫實現(xiàn)效果,但是在使用animation-list時,圖片也就11張,每張圖片大概560k左右,結(jié)果內(nèi)存溢出,崩潰 了,自己用了三張都崩潰;拿代碼說;

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(); 

結(jié)果setBackgroundResource出現(xiàn)內(nèi)存溢出,這個方法其實獲取drawable時候,會消耗很多內(nèi)存,很容易內(nèi)存溢出,崩潰。

3.解決方法:在網(wǎng)上找了個類,處理,結(jié)果我使用11張560k大小圖片,沒有內(nèi)存溢出;

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轉(zhuǎn)為byte字節(jié)數(shù)組  * *******/ 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   /***    * 性能更優(yōu)    * 在animation-list中設(shè)置時間    * **/   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 Context context,                   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, imageView, onComplete, 0);   }    // 5   private static void animateRawManually(final List<MyFrame> myFrames,                       final ImageView imageView, 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, 0, 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, imageView, onComplete,                   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, 0,                   nextFrame.bytes.length));           if (nextFrame.isReady) {             // Animate next frame             animateRawManually(myFrames, imageView, onComplete,                 frameNumber + 1);           } else {             nextFrame.isReady = true;           }          }       }).run();     }   }    //第二種方法   /***    * 代碼中控制時間,但不精確    * duration = 1000;    * ****/   public static void animateManuallyFromRawResource(       int animationDrawableResourceId, ImageView imageView,       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, 0,                       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, imageView, onComplete, 0);   }    private static void animateDrawableManually(       final AnimationDrawable animationDrawable,       final ImageView imageView, final Runnable onComplete,       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, imageView,                 onComplete, frameNumber + 1);           } else {             // Animation complete             if (onComplete != null) {               onComplete.run();             }           }         }       }     }, animationDrawable.getDuration(frameNumber));   }  } 

這里需要導(dǎo)入jar,

import org.apache.commons.io.IOUtils;

4.然后通過上述類,來調(diào)用自己的動畫xml,

MyAnimationDrawable.animateRawManuallyFromXML(R.drawable.anim_search,             search_scale_iv, new Runnable() {                @Override               public void run() {                 // TODO onStart                 // 動畫開始時回調(diào)                 log.d("","start");                                }             }, new Runnable() {                @Override               public void run() {                 // TODO onComplete                 // 動畫結(jié)束時回調(diào)                 log.d("","end");                                }             }); 

這樣在使用幀動畫時,可以有效的適度防止內(nèi)存溢出,誰還有什么辦法,歡迎交流!

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 根河市| 敦化市| 化德县| 泰来县| 长治县| 安平县| 合肥市| 拉萨市| 桃园市| 民权县| 伊川县| 聂拉木县| 淮阳县| 文登市| 宜城市| 保康县| 乐亭县| 汝阳县| 赤城县| 康定县| 运城市| 衡阳市| 油尖旺区| 铜梁县| 万宁市| 绥滨县| 逊克县| 微山县| 黄石市| 临潭县| 双江| 辛集市| 阿合奇县| 河东区| 绥德县| 浮梁县| 息烽县| 突泉县| 饶河县| 永清县| 樟树市|