解决animation-list加载多张帧动画导致OOM的问题---surfaceview用法

这次界面改版中有几个界面的动画实在酷炫,只有让UI出一组png用帧动画的形式展示了。心想着,这不简单:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item
        android:drawable="@mipmap/volume_00000"
        android:duration="100" />
    <item
        android:drawable="@mipmap/volume_00001"
        android:duration="100" />
    <item
        android:drawable="@mipmap/volume_00002"
        android:duration="100" />
    <item
        android:drawable="@mipmap/volume_00003"
        android:duration="100" />
</animation-list>

完事~~

但是:微笑微笑微笑


尼玛啊发火~~~~~~~~~将近6000张图片尴尬,我用脚趾头想都知道用animation-list肯定直接要爆炸了微笑微笑微笑

怎么办,么办,办?当时心情是崩溃的微笑微笑微笑


-----------------------------------------------------------------分割线-------------------------------------------------------------

聪明的大脑稍微这么一转 surfaceView

代码注释很详细不废话直接贴~~

package com.meizu.speaker.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.meizu.speaker.R;

/**
 * Created by zhangxiaotong on 2016/11/1.
 */
public class recycleSurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{

    private String TAG = this.getClass().getSimpleName();
    private final SurfaceHolder mHolder;
    private Thread mThread;
    private long mFrameSpaceTime = 80;  // 每帧图片的间隔时间
    private boolean mIsDraw = true;     // 画图开关
    private int mCurrentIndext = 0;     // 当前正在播放的png

    public int mBitmapResourceIds[] = {
            R.mipmap.menu_00002, R.mipmap.menu_00004, R.mipmap.menu_00006, R.mipmap.menu_00008, R.mipmap.menu_00010, R.mipmap.menu_00012,
            R.mipmap.menu_00014, R.mipmap.menu_00016, R.mipmap.menu_00018, R.mipmap.menu_00020, R.mipmap.menu_00022, R.mipmap.menu_00024,
            R.mipmap.menu_00026, R.mipmap.menu_00028, R.mipmap.menu_00030, R.mipmap.menu_00032, R.mipmap.menu_00034, R.mipmap.menu_00036,
            R.mipmap.menu_00038, R.mipmap.menu_00040, R.mipmap.menu_00042, R.mipmap.menu_00044, R.mipmap.menu_00046, R.mipmap.menu_00048,
            R.mipmap.menu_00050, R.mipmap.menu_00052, R.mipmap.menu_00054, R.mipmap.menu_00056, R.mipmap.menu_00058, R.mipmap.menu_00060,
            R.mipmap.menu_00062, R.mipmap.menu_00064, R.mipmap.menu_00066, R.mipmap.menu_00068, R.mipmap.menu_00070, R.mipmap.menu_00072,
            R.mipmap.menu_00074, R.mipmap.menu_00076, R.mipmap.menu_00078, R.mipmap.menu_00080, R.mipmap.menu_00082, R.mipmap.menu_00084,
            R.mipmap.menu_00086, R.mipmap.menu_00088, R.mipmap.menu_00090, R.mipmap.menu_00092, R.mipmap.menu_00094, R.mipmap.menu_00096,
            R.mipmap.menu_00098, R.mipmap.menu_00100, R.mipmap.menu_00102, R.mipmap.menu_00104, R.mipmap.menu_00106, R.mipmap.menu_00108,
            R.mipmap.menu_00110, R.mipmap.menu_00112, R.mipmap.menu_00114, R.mipmap.menu_00116, R.mipmap.menu_00118, R.mipmap.menu_00120,
            R.mipmap.menu_00122, R.mipmap.menu_00124, R.mipmap.menu_00126, R.mipmap.menu_00128, R.mipmap.menu_00130, R.mipmap.menu_00132,
            R.mipmap.menu_00134, R.mipmap.menu_00136, R.mipmap.menu_00138, R.mipmap.menu_00140, R.mipmap.menu_00142, R.mipmap.menu_00144,
            R.mipmap.menu_00146, R.mipmap.menu_00148, R.mipmap.menu_00150, R.mipmap.menu_00152, R.mipmap.menu_00154, R.mipmap.menu_00156,
            R.mipmap.menu_00158, R.mipmap.menu_00160, R.mipmap.menu_00162, R.mipmap.menu_00164, R.mipmap.menu_00166, R.mipmap.menu_00168,
            R.mipmap.menu_00170, R.mipmap.menu_00172, R.mipmap.menu_00174, R.mipmap.menu_00176, R.mipmap.menu_00178, R.mipmap.menu_00180,
            R.mipmap.menu_00182, R.mipmap.menu_00184, R.mipmap.menu_00186, R.mipmap.menu_00188, R.mipmap.menu_00190, R.mipmap.menu_00000
    };
    private Bitmap mBitmap;

    public recycleSurfaceView(Context context) {this(context,null);}

    public recycleSurfaceView(Context context, AttributeSet attrs) {this(context,attrs,0);}

    public recycleSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mHolder = this.getHolder();       // 获得surfaceholder
        mHolder.addCallback(this);        // 添加回调,这样三个方法才会执行

        setZOrderOnTop(true);
        mHolder.setFormat(PixelFormat.TRANSLUCENT);// 设置背景透明
    }

    /**
    首先继承SurfaceView,并实现SurfaceHolder.Callback接口,实现它的三个方法:
    surfaceCreated(SurfaceHolder holder):surface创建的时候调用,一般在该方法中启动绘图的线程。
    surfaceChanged(SurfaceHolder holder, int format, int width,int height):surface尺寸发生改变的时候调用,如横竖屏切换。
    surfaceDestroyed(SurfaceHolder holder) :surface被销毁的时候调用,如退出游戏画面,一般在该方法中停止绘图线程。
    还需要获得SurfaceHolder,并添加回调函数,这样这三个方法才会执行。
    */

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        Log.d(TAG, "surfaceCreated: ");
        if(mBitmapResourceIds == null){
            Log.e(TAG, "surfaceCreated: 图片资源为空");
            return;
        }
        mThread = new Thread(this);
        mThread.start();
        mIsDraw = true;
    }

    public void setmBitmapResourceIds(int[] mBitmapResourceIds) {
        this.mBitmapResourceIds = mBitmapResourceIds;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mIsDraw = false;
        try {
            Thread.sleep(mFrameSpaceTime);
            Log.d(TAG, "surfaceDestroyed: Thread " + mThread.getState());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        synchronized (mHolder) {         // 这里加锁为了以后控制这个绘制线程的wait与notify
            while (mIsDraw) {
                try {
                    drawView();
                    Thread.sleep(mFrameSpaceTime);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void drawView() {
        Log.i(TAG, "drawView: ");
        Canvas mCanvas = mHolder.lockCanvas();      // 锁定画布
        try {
            mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);        // 清除屏幕
            mCanvas.drawColor(Color.BLACK);

            mBitmap = BitmapFactory.decodeResource(getResources(), mBitmapResourceIds[mCurrentIndext]);
            mCanvas.drawBitmap(mBitmap, 0, 0, null);

            if (mCurrentIndext == mBitmapResourceIds.length - 1) {
                mCurrentIndext = 0;
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            mCurrentIndext++;
            if (mCanvas != null) {
                mHolder.unlockCanvasAndPost(mCanvas);       // 提交画布
            }
            recycle(mBitmap);  // 这里回收资源非常重要!
        }
    }

    private void recycle(Bitmap mBitmap) {
        if(mBitmap != null)
            mBitmap.recycle();
    }
}


布局文件:
    <com.meizu.speaker.view.recycleSurfaceView
     android:id="@+id/anim"
     android:layout_width="@dimen/common_margin_31"
     android:layout_height="@dimen/common_margin_240"
     android:layout_centerVertical="true"
     android:layout_marginStart="@dimen/common_margin_60"
     android:scaleType="fitXY"/> 


预览~~








  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值