我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

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; 
 
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 
   
  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(); 
    } 
  } 
  //第二种方法 
   
  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)); 
  } 
} 

这里需要导入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 逐帧动画创建实例详解Android之仿美团加载数据帧动画Android逐帧动画实现代码Android帧动画、补间动画、属性动画用法详解Android 动画(View动画,帧动画,属性动画)详细介绍Android动画之逐帧动画(Frame Animation)基础学习Android动画之逐帧动画(Frame Animation)实例详解Android编程之简单逐帧动画Frame的实现方法Android利用animation-list实现帧动画


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

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

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

PHP内存溢出的原因和解决方案

PHP内存溢出成因与解决方法PHP内存溢出常见原因包括庞大数据结构、循环引用和内存泄漏。可采取预防措施,如优化数据结构、避免无限递归和定期释放内存。另外,增加内存限制、启用内存缓存和使用64位PHP可优化配置。故障排除包括查看错误日志、启用内存调试和使用内存分析工具。定期审查代码并更新PHP版本也有助于降低溢出风险。
PHP内存溢出的原因和解决方案
2024-04-02

Android编程之内存溢出解决方案(OOM)实例总结

本文实例总结了Android编程之内存溢出解决方案(OOM)。分享给大家供大家参考,具体如下: 在最近做的工程中发现加载的图片太多或图片过大时经常出现OOM问题,找网上资料也提供了很多方法,但自己感觉有点乱,特此,今天在不同型号的三款安卓手
2022-06-06

vue项目内存溢出问题及解决方案

这篇文章主要介绍了vue项目内存溢出问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-01-28

Android加载图片内存溢出问题解决方法

1. 在Android软件开发过程中,图片处理是经常遇到的。 在将图片转换成Bitmap的时候,由于图片的大小不一样,当遇到很大的图片的时候会出现超出内存的问题,为了解决这个问题Android API提供了BitmapFactory.Opt
2022-06-06

Android 异步获取网络图片并处理导致内存溢出问题解决方法

测试环境为Adnroid 2.1以上。 1.AndroidManifest.xml 权限配置: 添加互联网访问权限: 代码如下: 2022-06-06

Android中使用webview时出现内存泄露如何解决

Android中使用webview时出现内存泄露如何解决,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1.避免在xml直接写webview控件,这样会引用activity,
2023-05-31

Android 中 Fragment 嵌套 Fragment使用存在的bug附完美解决方案

自从Android3.0引入了Fragment之后,使用Activity去嵌套一些Fragment的做法也变得更加流行,这确实是Fragment带来的一些优点,比如说:Fragment可以使你能够将activity分离成多个可重用的组件,每
2022-06-06

Mac退出移动硬盘时显示“磁盘无法推出,因为一个或多个程序正在使用它”解决方案

解决方法 1. 重启访达2. 重启电脑3. 终端命令行方法4. ```df -lh```不显示移动磁盘名称时的解决方法 1. 重启访达 按住option键,在底部程序坞的访达图标右键,选择重新启动。此时访达app会重启,之后尝试
2023-08-17

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录