Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 507|回复: 0

Android使用帧动画解决内存溢出问题

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-5 10:10:28 | 显示全部楼层 |阅读模式

    相信很多朋友在使用AnimationDrawable做帧动画时,图片过大或者数量过多,很容易就遇到内存溢出问题;

    图片过大有很多相关的处理方法,但使用xml配置文件加载数量过多的图片时(40-50张就出现溢出),就比较棘手。

    在stackoverflow找到的相关解决方法:http://stackoverflow.com/questions/8692328/causing-outofmemoryerror-in-frame-by-frame-animation-in-android

    <-------------------------------------------------------------------------------------------------->

    需要jar包:commons-io-1.4.jar

    工具类代码如下:

      1 import java.io.IOException;  
      2 import java.util.ArrayList;  
      3 import java.util.List;  
      4 import org.apache.commons.io.IOUtils;  
      5 import org.xmlpull.v1.XmlPullParser;  
      6 import org.xmlpull.v1.XmlPullParserException;  
      7 import android.content.Context;  
      8 import android.content.res.XmlResourceParser;  
      9 import android.graphics.BitmapFactory;  
     10 import android.graphics.drawable.AnimationDrawable;  
     11 import android.graphics.drawable.BitmapDrawable;  
     12 import android.graphics.drawable.Drawable;  
     13 import android.os.Handler;  
     14 import android.widget.ImageView;  
     15 
     23 public class MyAnimationDrawable {
     24     public static class MyFrame {  
     25         byte[] bytes;  
     26         int duration;  
     27         Drawable drawable;  
     28         boolean isReady = false;  
     29     }  
     30   
     31     public interface OnDrawableLoadedListener {  
     32         public void onDrawableLoaded(List<MyFrame> myFrames);  
     33     }  
     34   
     35     
     40     public static void animateRawManuallyFromXML(int resourceId,  
     41             final ImageView imageView, final Runnable onStart,  
     42             final Runnable onComplete) {  
     43         loadRaw(resourceId, imageView.getContext(),  
     44                 new OnDrawableLoadedListener() {  
     45                     @Override  
     46                     public void onDrawableLoaded(List<MyFrame> myFrames) {  
     47                         if (onStart != null) {  
     48                             onStart.run();  
     49                         }  
     50                         animateRawManually(myFrames, imageView, onComplete);  
     51                     }  
     52                 });  
     53     }  
     54   
     55     //
     56     private static void loadRaw(final int resourceId, final Context context,  
     57             final OnDrawableLoadedListener onDrawableLoadedListener) {  
     58         loadFromXml(resourceId, context, onDrawableLoadedListener);  
     59     }  
     60   
     61     //
     62     private static void loadFromXml(final int resourceId,  
     63             final Context context,  
     64             final OnDrawableLoadedListener onDrawableLoadedListener) {  
     65         new Thread(new Runnable() {  
     66             @Override  
     67             public void run() {  
     68                 final ArrayList<MyFrame> myFrames = new ArrayList<MyFrame>();  
     69   
     70                 XmlResourceParser parser = context.getResources().getXml(  
     71                         resourceId);  
     72   
     73                 try {  
     74                     int eventType = parser.getEventType();  
     75                     while (eventType != XmlPullParser.END_DOCUMENT) {  
     76                         if (eventType == XmlPullParser.START_DOCUMENT) {  
     77   
     78                         } else if (eventType == XmlPullParser.START_TAG) {  
     79   
     80                             if (parser.getName().equals("item")) {  
     81                                 byte[] bytes = null;  
     82                                 int duration = 1000;  
     83   
     84                                 for (int i = 0; i < parser.getAttributeCount(); i++) {  
     85                                     if (parser.getAttributeName(i).equals(  
     86                                             "drawable")) {  
     87                                         int resId = Integer.parseInt(parser  
     88                                                 .getAttributeValue(i)  
     89                                                 .substring(1));  
     90                                         bytes = IOUtils.toByteArray(context  
     91                                                 .getResources()  
     92                                                 .openRawResource(resId));  
     93                                     } else if (parser.getAttributeName(i)  
     94                                             .equals("duration")) {  
     95                                         duration = parser.getAttributeIntValue(  
     96                                                 i, 1000);  
     97                                     }  
     98                                 }  
     99   
    100                                 MyFrame myFrame = new MyFrame();  
    101                                 myFrame.bytes = bytes;  
    102                                 myFrame.duration = duration;  
    103                                 myFrames.add(myFrame);  
    104                             }  
    105   
    106                         } else if (eventType == XmlPullParser.END_TAG) {  
    107   
    108                         } else if (eventType == XmlPullParser.TEXT) {  
    109   
    110                         }  
    111   
    112                         eventType = parser.next();  
    113                     }  
    114                 } catch (IOException e) {  
    115                     e.printStackTrace();  
    116                 } catch (XmlPullParserException e2) {  
    117                     // TODO: handle exception  
    118                     e2.printStackTrace();  
    119                 }  
    120   
    121                 // Run on UI Thread  
    122                 new Handler(context.getMainLooper()).post(new Runnable() {  
    123                     @Override  
    124                     public void run() {  
    125                         if (onDrawableLoadedListener != null) {  
    126                             onDrawableLoadedListener.onDrawableLoaded(myFrames);  
    127                         }  
    128                     }  
    129                 });  
    130             }  
    131         }).run();  
    132     }  
    133   
    134     //
    135     private static void animateRawManually(List<MyFrame> myFrames,  
    136             ImageView imageView, Runnable onComplete) {  
    137         animateRawManually(myFrames, imageView, onComplete, 0);  
    138     }  
    139   
    140     //
    141     private static void animateRawManually(final List<MyFrame> myFrames,  
    142             final ImageView imageView, final Runnable onComplete,  
    143             final int frameNumber) {  
    144         final MyFrame thisFrame = myFrames.get(frameNumber);  
    145   
    146         if (frameNumber == 0) {  
    147             thisFrame.drawable = new BitmapDrawable(imageView.getContext()  
    148                     .getResources(), BitmapFactory.decodeByteArray(  
    149                     thisFrame.bytes, 0, thisFrame.bytes.length));  
    150         } else {  
    151             MyFrame previousFrame = myFrames.get(frameNumber - 1);  
    152             ((BitmapDrawable) previousFrame.drawable).getBitmap().recycle();  
    153             previousFrame.drawable = null;  
    154             previousFrame.isReady = false;  
    155         }  
    156   
    157         imageView.setImageDrawable(thisFrame.drawable);  
    158         new Handler().postDelayed(new Runnable() {  
    159             @Override  
    160             public void run() {  
    161                 // Make sure ImageView hasn't been changed to a different Image  
    162                 // in this time  
    163                 if (imageView.getDrawable() == thisFrame.drawable) {  
    164                     if (frameNumber + 1 < myFrames.size()) {  
    165                         MyFrame nextFrame = myFrames.get(frameNumber + 1);  
    166   
    167                         if (nextFrame.isReady) {  
    168                             // Animate next frame  
    169                             animateRawManually(myFrames, imageView, onComplete,  
    170                                     frameNumber + 1);  
    171                         } else {  
    172                             nextFrame.isReady = true;  
    173                         }  
    174                     } else {  
    175                         if (onComplete != null) {  
    176                             onComplete.run();  
    177                         }  
    178                     }  
    179                 }  
    180             }  
    181         }, thisFrame.duration);  
    182   
    183         // Load next frame  
    184         if (frameNumber + 1 < myFrames.size()) {  
    185             new Thread(new Runnable() {  
    186                 @Override  
    187                 public void run() {  
    188                     MyFrame nextFrame = myFrames.get(frameNumber + 1);  
    189                     nextFrame.drawable = new BitmapDrawable(imageView  
    190                             .getContext().getResources(),  
    191                             BitmapFactory.decodeByteArray(nextFrame.bytes, 0,  
    192                                     nextFrame.bytes.length));  
    193                     if (nextFrame.isReady) {  
    194                         // Animate next frame  
    195                         animateRawManually(myFrames, imageView, onComplete,  
    196                                 frameNumber + 1);  
    197                     } else {  
    198                         nextFrame.isReady = true;  
    199                     }  
    200   
    201                 }  
    202             }).run();  
    203         }  
    204     }  
    205   
    206     //带时间的方法 
    211     public static void animateManuallyFromRawResource(  
    212             int animationDrawableResourceId, ImageView imageView,  
    213             Runnable onStart, Runnable onComplete, int duration) throws IOException,  
    214             XmlPullParserException {  
    215         AnimationDrawable animationDrawable = new AnimationDrawable();  
    216   
    217         XmlResourceParser parser = imageView.getContext().getResources()  
    218                 .getXml(animationDrawableResourceId);  
    219   
    220         int eventType = parser.getEventType();  
    221         while (eventType != XmlPullParser.END_DOCUMENT) {  
    222             if (eventType == XmlPullParser.START_DOCUMENT) {  
    223   
    224             } else if (eventType == XmlPullParser.START_TAG) {  
    225   
    226                 if (parser.getName().equals("item")) {  
    227                     Drawable drawable = null;  
    228   
    229                     for (int i = 0; i < parser.getAttributeCount(); i++) {  
    230                         if (parser.getAttributeName(i).equals("drawable")) {  
    231                             int resId = Integer.parseInt(parser  
    232                                     .getAttributeValue(i).substring(1));  
    233                             byte[] bytes = IOUtils.toByteArray(imageView  
    234                                     .getContext().getResources()  
    235                                     .openRawResource(resId));//IOUtils.readBytes  
    236                             drawable = new BitmapDrawable(imageView  
    237                                     .getContext().getResources(),  
    238                                     BitmapFactory.decodeByteArray(bytes, 0,  
    239                                             bytes.length));  
    240                         } else if (parser.getAttributeName(i)  
    241                                 .equals("duration")) {  
    242                             duration = parser.getAttributeIntValue(i, 66);  
    243                         }  
    244                     }  
    245   
    246                     animationDrawable.addFrame(drawable, duration);  
    247                 }  
    248   
    249             } else if (eventType == XmlPullParser.END_TAG) {  
    250   
    251             } else if (eventType == XmlPullParser.TEXT) {  
    252   
    253             }  
    254   
    255             eventType = parser.next();  
    256         }  
    257   
    258         if (onStart != null) {  
    259             onStart.run();  
    260         }  
    261         animateDrawableManually(animationDrawable, imageView, onComplete, 0);  
    262     }  
    263   
    264     private static void animateDrawableManually(  
    265             final AnimationDrawable animationDrawable,  
    266             final ImageView imageView, final Runnable onComplete,  
    267             final int frameNumber) {  
    268         final Drawable frame = animationDrawable.getFrame(frameNumber);  
    269         imageView.setImageDrawable(frame);  
    270         new Handler().postDelayed(new Runnable() {  
    271             @Override  
    272             public void run() {  
    273                 // Make sure ImageView hasn't been changed to a different Image  
    274                 // in this time  
    275                 if (imageView.getDrawable() == frame) {  
    276                     if (frameNumber + 1 < animationDrawable.getNumberOfFrames()) {  
    277                         // Animate next frame  
    278                         animateDrawableManually(animationDrawable, imageView,  
    279                                 onComplete, frameNumber + 1);  
    280                     } else {  
    281                         // Animation complete  
    282                         if (onComplete != null) {  
    283                             onComplete.run();  
    284                         }  
    285                     }  
    286                 }  
    287             }  
    288         }, animationDrawable.getDuration(frameNumber));  
    289     }  
    290 }

    调用方法如下:(帧动画的使用这里不说了,比较容易实现)

    参数:anm_image_view-->自定义的xml文件;  anm_image_view-->展示的ImageView控件;
     1 MyAnimationDrawable.animateRawManuallyFromXML(R.anim.welcome_anim,
     2                 anm_image_view, new Runnable() {
     3 
     4                     @Override
     5                     public void run() {
     6                         // TODO onStart
     7                         // 动画开始时回调
     9                     }
    10                 }, new Runnable() {
    11 
    12                     @Override
    13                     public void run() {
    14                         // TODO onComplete
    15                         // 动画结束时回调
    18                     }
    19                 });
    25     }

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-12 08:46 , Processed in 0.066110 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表