Android逐帧动画,逐帧动画加载图片过多时OOM异常的解决和替代方法

1.首先添加逐帧动画

播放逐帧动画,在工程中res目录下创建一个anim文件夹,添加动画anim_welcome.xml文件如下:


<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true">
    <item android:drawable="@drawable/meet_01" android:duration="500" />
    <item android:drawable="@drawable/meet_02" android:duration="500" />
    <item android:drawable="@drawable/meet_03" android:duration="500" />
animation-list>

之后,为ImageView控件设置动画,并可看到想要的逐帧动画的效果:

    ImageView imgView_meet =(ImageView)findViewById(R.id.imgView_meet);
    imgView_meet.setBackgroundResource(R.anim.anim_meet);
    AnimationDrawable animDrawable = (AnimationDrawable)imgView_meet.getBackground();
    animDrawable.start();

2.Android逐帧动画造成OOM异常

由于逐帧动画加载的图片很多,不一定只有2/3张,很可能达到10张以上甚至几十张,易造成OOM异常崩溃的问题,解决方法如下。

方法一:

(各种百度->发现帧动画一次性加载10张图片,易造成OOM,故修改成分布加载10张图片,不说了,直接上代码:)

package com.child.drawdemo;

import android.widget.ImageView;

public class SceneAnimation {
    private ImageView mImageView;
    private int[] mFrameRess;
    private int[] mDurations;
    private int mDuration;

    private int mLastFrameNo;
    private long mBreakDelay;

    public SceneAnimation(ImageView pImageView, int[] pFrameRess,
       int[] pDurations) {
      mImageView = pImageView;
      mFrameRess = pFrameRess;
      mDurations = pDurations;
      mLastFrameNo = pFrameRess.length - 1;

      mImageView.setBackgroundResource(mFrameRess[0]);
      play(1);
     }

    public SceneAnimation(ImageView pImageView, int[] pFrameRess, int pDuration) {
      mImageView = pImageView;
      mFrameRess = pFrameRess;
      mDuration = pDuration;
      mLastFrameNo = pFrameRess.length - 1;

      mImageView.setBackgroundResource(mFrameRess[0]);
      playConstant(1);
     }

    public SceneAnimation(ImageView pImageView, int[] pFrameRess,
       int pDuration, long pBreakDelay) {
      mImageView = pImageView;
      mFrameRess = pFrameRess;
      mDuration = pDuration;
      mLastFrameNo = pFrameRess.length - 1;
      mBreakDelay = pBreakDelay;

      mImageView.setBackgroundResource(mFrameRess[0]);
      playConstant(1);
     }

    private void play(final int pFrameNo) {
        mImageView.postDelayed(new Runnable() {
            public void run() {
                mImageView.setBackgroundResource(mFrameRess[pFrameNo]);
                if (pFrameNo == mLastFrameNo)
                    play(0);
                else
                    play(pFrameNo + 1);
            }
        }, mDurations[pFrameNo]);
    }

    private void playConstant(final int pFrameNo) {
        mImageView.postDelayed(new Runnable() {
            public void run() {
                mImageView.setBackgroundResource(mFrameRess[pFrameNo]);

                if (pFrameNo == mLastFrameNo)
                    playConstant(0);
                else
                    playConstant(pFrameNo + 1);
            }
        }, pFrameNo == mLastFrameNo && mBreakDelay > 0 ? mBreakDelay
                : mDuration);
    }
}

之后,并可以对上述类进行调用(首先定义一堆要加载的图片,之后调用类的构造函数即可):

    private int[] meetPics = new int[]{
                R.drawable.meet_01, R.drawable.meet_02, R.drawable.meet_03, 
                R.drawable.meet_04, R.drawable.meet_05, R.drawable.meet_06,
                R.drawable.meet_07, R.drawable.meet_08, R.drawable.meet_09,
                R.drawable.meet_10, R.drawable.meet_11, R.drawable.meet_12,
                R.drawable.meet_13, R.drawable.meet_14, R.drawable.meet_15,
                R.drawable.meet_16, R.drawable.meet_17, R.drawable.meet_18,
                R.drawable.meet_19, R.drawable.meet_20, R.drawable.meet_21,
                R.drawable.meet_22, R.drawable.meet_23, R.drawable.meet_24,
                R.drawable.meet_25, R.drawable.meet_26, R.drawable.meet_27,
                R.drawable.meet_28, R.drawable.meet_29, R.drawable.meet_30,
                R.drawable.meet_31, R.drawable.meet_32, R.drawable.meet_33,
                R.drawable.meet_34, R.drawable.meet_35, R.drawable.meet_36,
                R.drawable.meet_37, R.drawable.meet_38, R.drawable.meet_39,
                R.drawable.meet_40, R.drawable.meet_41, R.drawable.meet_42,
                R.drawable.meet_43, R.drawable.meet_44, R.drawable.meet_45,
                R.drawable.meet_46, R.drawable.meet_47, R.drawable.meet_48,
                R.drawable.meet_49};

    SceneAnimation anim = new SceneAnimation(imgView_meet, meetPics, 40);

方法二:(直接加载gif动画达到效果)

【其中可采用如下两种方式】

1.直接采用GitHub上的gif开源框架:

android-gif-drawable的源代码下载地址:https://github.com/koral--/android-gif-drawable

2.利用WebView控件,将gif动画文件作为web的一部分进行加载:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

LinearLayout>
private WebView webView;
----------
webView = (WebView)findViewById(R.id.webView);
webView.loadDataWithBaseURL(null,"
"
, "text/html", "UTF-8",null);

采用上述各种方法来达到帧动画的效果时,图片或gif每帧的图像不能过大,太大将会造成播放卡顿或闪烁等各种问题。

你可能感兴趣的:(Android)