博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android使用帧动画解决内存溢出问题
阅读量:6317 次
发布时间:2019-06-22

本文共 11229 字,大约阅读时间需要 37 分钟。

相信很多朋友在使用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
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
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
myFrames = new ArrayList
(); 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
myFrames, 136 ImageView imageView, Runnable onComplete) { 137 animateRawManually(myFrames, imageView, onComplete, 0); 138 } 139 140 //141 private static void animateRawManually(final List
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                     @Override13                     public void run() {14                         // TODO onComplete15                         // 动画结束时回调18                     }19                 });25     }

 

转载于:https://www.cnblogs.com/mcfawa/p/5192335.html

你可能感兴趣的文章
使用ArrayList时设置初始容量的重要性
查看>>
Java Web-----JSP与Servlet(一)
查看>>
Maven搭建SpringMVC+Mybatis项目详解
查看>>
关于量子理论:最初无意的简化,和一些人有意的强化和放大
查看>>
CentOS 6.9通过RPM安装EPEL源(http://dl.fedoraproject.org)
查看>>
“区块链”并没有什么特别之处
查看>>
没有功能需求设计文档?对不起,拒绝开发!
查看>>
4星|《先发影响力》:影响与反影响相关的有趣的心理学研究综述
查看>>
IE8调用window.open导出EXCEL文件题目
查看>>
python之 列表常用方法
查看>>
vue-cli脚手架的搭建
查看>>
在网页中加入百度搜索框实例代码
查看>>
在Flex中动态设置icon属性
查看>>
采集音频和摄像头视频并实时H264编码及AAC编码
查看>>
3星|《三联生活周刊》2017年39期:英国皇家助产士学会于2017年5月悄悄修改了政策,不再鼓励孕妇自然分娩了...
查看>>
高级Linux工程师常用软件清单
查看>>
堆排序算法
查看>>
folders.cgi占用系统大量资源
查看>>
路由器ospf动态路由配置
查看>>
zabbix监控安装与配置
查看>>