android使用帧动画防止内存溢出工具类

jar包下载地址  http://download.csdn.net/download/menglele1314/9278751

原文链接:http://stackoverflow.com/questions/8692328/causing-outofmemoryerror-in-frame-by-frame-animation-in-android

使用方法1:

MyAnimationDrawable.animateRawManuallyFromXML(R.anim.animation_loading_unity, anm_image_test01, 
				new Runnable() {
					
					@Override
					public void run() {
						// TODO onStart
//						Toast.makeText(getApplicationContext(), "start", 0).show();
					}
				}, new Runnable() {
					
					@Override
					public void run() {
						// TODO onComplete
						initview02();
//						Toast.makeText(getApplicationContext(), "onComplete", 0).show();
					}
				});
使用方法2:

try {
			MyAnimationDrawable.animateManuallyFromRawResource(R.anim.animation_loading_unity,anm_image_test01 ,
					new Runnable() {
						
						@Override
						public void run() {
							// TODO start
//							Toast.makeText(getApplicationContext(), "start", 0).show();
						}
					}, 
					new Runnable() {
						
						@Override
						public void run() {
							// TODO complete
							init_view();
//							Toast.makeText(getApplicationContext(), "complete", 0).show();
						}
					},10000);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (XmlPullParserException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
推荐使用第一种方法,废话不多说,源码如下:

package com.mojichina.demo.util;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
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;

/****
 * 此工具类源于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 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));
	}
	
}


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值