在stackoverflow找到的相关解决方法:http://stackoverflow.com/questions/8692328/causing-outofmemoryerror-in-frame-by-frame-animation-in-android
<-------------------------------------------------------------------------------------------------->
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 }
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 }