美文网首页
简单方便的帧动画加载库,解决帧动画OOM的问题

简单方便的帧动画加载库,解决帧动画OOM的问题

作者: Kimger | 来源:发表于2018-07-13 00:49 被阅读0次

    最近遇到了需要播放大量帧动画(100张以上)的需求,使用传统xml帧动画方式,会频繁OOM,为了解决这个问题,进行了几种尝试,目前的解决方案如下:

    传统帧动画

    • 我们需要在drawable目录下创建动画集animalist.xml
      <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
        android:oneshot="false">
        <item
            android:drawable="@mipmap/image_1"
            android:duration="50" />
        <item
            android:drawable="@mipmap/image_2"
            android:duration="50" />
         <!--  省略...  -->
        <item
            android:drawable="@mipmap/image_99"
            android:duration="50" />
        <item
            android:drawable="@mipmap/image_100"
            android:duration="50" />
        </animation-list>
      
      
      

    经过尝试,图片不是很大的时候,大概到20几张图片的时候就会OOM

    解决方案

    写了一个处理类,使用方法很简单下边直接上代码

    先贴一下调用代码,真的很简单

    FrameLoader.into(mImageView).load(mTest).setEndlessLoop(true).setLoopCount(3).play(200);

    直接上代码,懒得看的人可以直接去看Github源码

    Github地址

    这是核心处理类

    /**
     * Created with Android Studio.
     *
     * @author Kimger
     * @email kimger@onetos.cc
     * @date 2018-7-13  00:01
     */
    
    public class Process {
        /**
         * 播方动画的相应布局
         */
        private ImageView mImageView;
        /**
         * 播放动画的图片数组
         */
        private int[] mImageRes;
        /**
         * 是否需要停止
         */
        private boolean stop;
        /**
         * 记录播放状态
         */
        private boolean playing;
        /**
         * 当前播放第*张
         */
        private int pImageNo;
        /**
         * 图片刷新频率
         */
        private int pImageFrequency;
        /**
         * 是否无限循环播放
         */
        private boolean endlessLoop = false;
        /**
         * 循环次数,不定义默认为1
         */
        private int loopCount = 1;
        /**
         * 记录当前循环了几次
         */
        private int countCache;
    
        private String mTag = getClass().getName();
    
        private static Process mInstance;
    
        private static List<ImageView> mObjects ;
    
        private static Map<ImageView, Process> mProcessMap;
    
        private static Pools.SynchronizedPool<Process> sPool = new Pools.SynchronizedPool<>(20);
    
    
        /**
         * 创建新的对象
         *
         * @return
         */
        public static Process build(ImageView tag){
            mInstance = obtain();
            mInstance.into(tag);
            return mInstance;
        }
    
        public static Process obtain(){
            Process acquire = sPool.acquire();
            return (acquire != null) ? acquire : new Process();
        }
    
        public void recycle(){
            sPool.release(this);
        }
    
        /**
         * 设置动画的ImageView
         *
         * @param pImageView
         * @return
         */
        private Process into(ImageView pImageView) {
            stop = true;
            if (mImageView != null) {
                mImageView.removeCallbacks(mRunnable);
            }
            if (pImageView != mImageView) {
                stop();
            }
            this.mImageRes = null;
            this.mImageView = pImageView;
            return mInstance;
        }
    
        /**
         * 设置动画数组文件
         *
         * @param pImageRes
         * @return
         */
        public Process load(int[] pImageRes) {
            this.mImageRes = pImageRes;
            return mInstance;
        }
    
        /**
         * 开始播放
         *
         * @param pImageNo
         * @param frequency
         */
        public Process play(int pImageNo, int frequency) {
            stop = false;
            this.pImageNo = pImageNo;
            this.pImageFrequency = frequency;
            mImageView.postDelayed(mRunnable, frequency);
            return mInstance;
        }
    
        public Process play(int frequency) {
            return play(0, frequency);
        }
    
        private Runnable mRunnable = new Runnable() {
            @Override
            public void run() {
                if (stop) {
                    playing = false;
                    return;
                } else {
                    mImageView.setImageResource(mImageRes[pImageNo]);
                    if (pImageNo >= mImageRes.length - 1) {
                        countCache++;
                        if (endlessLoop) {
                            pImageNo = 0;
                            play(pImageNo, pImageFrequency);
                            playing = true;
                        } else {
                            if (countCache >= loopCount) {
                                playing = false;
                                stop();
                                return;
                            } else {
                                pImageNo = 0;
                                play(pImageNo, pImageFrequency);
                                playing = true;
                            }
                        }
                    } else {
                        play(pImageNo + 1, pImageFrequency);
                        playing = true;
                    }
                }
            }
        };
    
        public boolean isStop() {
            return stop;
        }
    
        private void setStop(boolean stop) {
            this.stop = stop;
        }
    
        /**
         * 停止播放
         */
        public void stop() {
            setStop(true);
            countCache = 0;
            if (mImageView != null) {
                mImageView.removeCallbacks(mRunnable);
                System.gc();
                recycle();
            }
            if (mProcessMap != null) {
                mProcessMap.clear();
            }
            if (mObjects != null) {
                mObjects.clear();
            }
    
        }
    
        public boolean isPlaying() {
            return playing;
        }
    
        /**
         * 是否无限循环
         */
        public Process setEndlessLoop(boolean endlessLoop) {
            this.endlessLoop = endlessLoop;
            return mInstance;
        }
    
        /**
         * 循环次数
         */
        public Process setLoopCount(int loopCount) {
            this.loopCount = loopCount;
            return mInstance;
        }
    }
    

    Manager类,留给后续添加功能的空间

    /**
     * Created with Android Studio.
     *
     * @author Kimger
     * @email kimger@onetos.cc
     * @date 2018-7-13  00:20
     */
    
    public class ProcessManager {
        
        private static ProcessManager mInstance;
    
        public static ProcessManager get(){
            if (mInstance == null) {
                synchronized (ProcessManager.class){
                    if (mInstance == null) {
                        mInstance = new ProcessManager();
                        
                    }
                }
            }
            return mInstance;
        }
    }
    

    这是调用类

    /**
     * Create with Android Studio.
     *
     * @author Kimger
     * @email kimger@onetos.cc
     * @date 2018-7-13 00:30
     */
    
    public class FrameLoader {
    
        public static Process into(ImageView tag){
            return Process.build(tag);
        }
        
        /**
         * 此功能暂时无法使用
         */
        public static Process getProcessByTag(ImageView tag){
            Map<ImageView, Process> imageViewProcessMap = ProcessManager.get().getmProcessMap();
            if (imageViewProcessMap != null) {
                return imageViewProcessMap.get(tag);
            }
            return null;
        }
    
    }
    

    然后就可以愉快的去使用帧动画了,亲测二百张也没什么问题。

    相关文章

      网友评论

          本文标题:简单方便的帧动画加载库,解决帧动画OOM的问题

          本文链接:https://www.haomeiwen.com/subject/qfmdpftx.html