zoukankan      html  css  js  c++  java
  • Android使用帧动画内存溢出解决方法

    Android使用帧动画内存溢出解决方法
    https://blog.csdn.net/daitu_liang/article/details/52336015
    https://blog.csdn.net/wanmeilang123/article/details/53929484

    causing-outofmemoryerror-in-frame-by-frame-animation-in-android
    https://stackoverflow.com/questions/8692328/causing-outofmemoryerror-in-frame-by-frame-animation-in-android

    Apache Commons IO
    http://commons.apache.org/proper/commons-io/description.html

    https://github.com/square/leakcanary

    LeakCanary 中文使用说明
    https://www.liaohuqiu.net/cn/posts/leak-canary-read-me/


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

    这里需要导入jar,
    import org.apache.commons.io.IOUtils; 相关包很多,我只是拿 了需要的jar,下载地址:http://commons.apache.org/proper/commons-io/description.html

    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");  
                                      
                                }  
                            });  

    这样在使用帧动画时,可以有效的适度防止内存溢出

  • 相关阅读:
    About unsign in Java
    Heart Shape Function
    Java内存分配与垃圾回收的关系
    Android Volume Button Listener
    Android Opensource Lib
    Android Lock Screen Orientation
    JS moveStart和moveEnd方法(TextRange对象查找与选择)
    一个简单的遮罩层效果
    IE中的条件注释(<![if lt IE 7]><![endif]>)
    document.execCommand()用法说明
  • 原文地址:https://www.cnblogs.com/bluestorm/p/9173405.html
Copyright © 2011-2022 走看看