簡單方便的幀動(dòng)畫加載庫,解決幀動(dòng)畫OOM的問題

最近遇到了需要播放大量幀動(dòng)畫(100張以上)的需求芍锦,使用傳統(tǒng)xml幀動(dòng)畫方式掏湾,會(huì)頻繁O(jiān)OM裹虫,為了解決這個(gè)問題,進(jìn)行了幾種嘗試融击,目前的解決方案如下:

傳統(tǒng)幀動(dòng)畫

  • 我們需要在drawable目錄下創(chuàng)建動(dòng)畫集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>
    
    
    

經(jīng)過嘗試筑公,圖片不是很大的時(shí)候,大概到20幾張圖片的時(shí)候就會(huì)OOM

解決方案

寫了一個(gè)處理類尊浪,使用方法很簡單下邊直接上代碼

先貼一下調(diào)用代碼,真的很簡單

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 {
    /**
     * 播方動(dòng)畫的相應(yīng)布局
     */
    private ImageView mImageView;
    /**
     * 播放動(dòng)畫的圖片數(shù)組
     */
    private int[] mImageRes;
    /**
     * 是否需要停止
     */
    private boolean stop;
    /**
     * 記錄播放狀態(tài)
     */
    private boolean playing;
    /**
     * 當(dāng)前播放第*張
     */
    private int pImageNo;
    /**
     * 圖片刷新頻率
     */
    private int pImageFrequency;
    /**
     * 是否無限循環(huán)播放
     */
    private boolean endlessLoop = false;
    /**
     * 循環(huán)次數(shù)匣屡,不定義默認(rèn)為1
     */
    private int loopCount = 1;
    /**
     * 記錄當(dāng)前循環(huán)了幾次
     */
    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);


    /**
     * 創(chuàng)建新的對象
     *
     * @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);
    }

    /**
     * 設(shè)置動(dòng)畫的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;
    }

    /**
     * 設(shè)置動(dòng)畫數(shù)組文件
     *
     * @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;
    }

    /**
     * 是否無限循環(huán)
     */
    public Process setEndlessLoop(boolean endlessLoop) {
        this.endlessLoop = endlessLoop;
        return mInstance;
    }

    /**
     * 循環(huán)次數(shù)
     */
    public Process setLoopCount(int loopCount) {
        this.loopCount = loopCount;
        return mInstance;
    }
}

Manager類,留給后續(xù)添加功能的空間

/**
 * 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;
    }
}

這是調(diào)用類

/**
 * 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);
    }
    
    /**
     * 此功能暫時(shí)無法使用
     */
    public static Process getProcessByTag(ImageView tag){
        Map<ImageView, Process> imageViewProcessMap = ProcessManager.get().getmProcessMap();
        if (imageViewProcessMap != null) {
            return imageViewProcessMap.get(tag);
        }
        return null;
    }

}

然后就可以愉快的去使用幀動(dòng)畫了拇涤,親測二百張也沒什么問題捣作。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市鹅士,隨后出現(xiàn)的幾起案子券躁,更是在濱河造成了極大的恐慌,老刑警劉巖如绸,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘱朽,死亡現(xiàn)場離奇詭異,居然都是意外死亡怔接,警方通過查閱死者的電腦和手機(jī)搪泳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扼脐,“玉大人岸军,你說我怎么就攤上這事⊥呶辏” “怎么了艰赞?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長肚吏。 經(jīng)常有香客問我方妖,道長,這世上最難降的妖魔是什么罚攀? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任党觅,我火速辦了婚禮雌澄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘杯瞻。我一直安慰自己镐牺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布魁莉。 她就那樣靜靜地躺著睬涧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旗唁。 梳的紋絲不亂的頭發(fā)上畦浓,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機(jī)與錄音逆皮,去河邊找鬼宅粥。 笑死,一個(gè)胖子當(dāng)著我的面吹牛电谣,可吹牛的內(nèi)容都是我干的秽梅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼剿牺,長吁一口氣:“原來是場噩夢啊……” “哼企垦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起晒来,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤钞诡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后湃崩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荧降,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年攒读,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了朵诫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡薄扁,死狀恐怖剪返,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情邓梅,我是刑警寧澤脱盲,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站日缨,受9級特大地震影響钱反,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一面哥、第九天 我趴在偏房一處隱蔽的房頂上張望乙各。 院中可真熱鬧,春花似錦幢竹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至驶乾,卻和暖如春邑飒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背级乐。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工疙咸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人风科。 一個(gè)月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓撒轮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贼穆。 傳聞我的和親對象是個(gè)殘疾皇子题山,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 媳婦和婆婆同是女人,自古至今總是互相為難故痊,甚至是刁難顶瞳!為什么? 中國的婆婆大人潛意識(shí)里的媳婦應(yīng)...
    琳兒貝貝閱讀 1,097評論 0 3
  • 一直打野愕秫,然后出山慨菱?那是順風(fēng)局,低端局戴甩! 高端局的套路是符喝,打野,抓住機(jī)會(huì)配合隊(duì)友殺人等恐!打野殺人洲劣,打野殺人! 優(yōu)先出...
    烏龜?shù)穆?/span>閱讀 226評論 0 0