帧动画多线程加载
程序员文章站
2022-03-02 08:18:05
...
帧动画在使用时,很容易造成卡顿。此代码使用多线程动态加载,防止卡顿。
使用方法:
int[] right_res_id = new int[]{R.drawable.r_00072, R.drawable.r_00073, R.drawable.r_00074, R.drawable.r_00075};
final AnimationsContainer.FramesSequenceAnimation rightAnim =
AnimationsContainer.getInstance(this,right_res_id,58).createProgressDialogAnim(imgRight);
rightAnim.setOnAnimStopListener(new AnimationsContainer.OnAnimationStoppedListener() {
@Override
public void AnimationStopped() {
// TODO
}
});
//rightAnim.loop(true);
//rightAnim.stop();
rightAnim.start();
代码 AnimationsContainer.java
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Handler;
import android.widget.ImageView;
import java.lang.ref.SoftReference;
/**
* 帧动画加载器
*/
public class AnimationsContainer {
private int DelayMillis = 58; // 每帧播放时间,毫秒
private int[] resId;
private Context mContext;
// 单例
private static final AnimationsContainer mInstance = new AnimationsContainer();
private AnimationsContainer() {
}
//获取单例
public static AnimationsContainer getInstance(Context context, int[] resId, int fps) {
mInstance.setResId(context, resId, fps);
return mInstance;
}
private void setResId(Context context, int[] resId, int delayMillis) {
this.mContext = context;
this.resId = resId;
this.DelayMillis = delayMillis;
}
/**
* @param imageView
* @return progress dialog animation
*/
public FramesSequenceAnimation createProgressDialogAnim(ImageView imageView) {
return new FramesSequenceAnimation(imageView, resId, DelayMillis);
}
/**
* 循环读取帧---循环播放帧
*/
public class FramesSequenceAnimation {
private int[] mFrames; // 帧数组
private int mIndex; // 当前帧
private boolean mShouldRun; // 开始/停止播放用
private boolean mIsRunning; // 动画是否正在播放,防止重复播放
private SoftReference<ImageView> mSoftReferenceImageView; // 软引用ImageView,以便及时释放掉
private Handler mHandler;
private int mDelayMillis;
private boolean isLoop = false;
private OnAnimationStoppedListener mOnAnimationStoppedListener; //播放停止监听
private Bitmap mBitmap = null;
private BitmapFactory.Options mBitmapOptions;//Bitmap管理类,可有效减少Bitmap的OOM问题
public FramesSequenceAnimation(ImageView imageView, int[] frames, int mDelayMillis) {
mHandler = new Handler();
mFrames = frames;
mIndex = -1;
mSoftReferenceImageView = new SoftReference<ImageView>(imageView);
mShouldRun = false;
mIsRunning = false;
this.mDelayMillis = mDelayMillis;//帧动画时间间隔,毫秒
imageView.setImageResource(mFrames[0]);
// 当图片大小类型相同时进行复用,避免频繁GC
if (Build.VERSION.SDK_INT >= 11) {
Bitmap bmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
int width = bmp.getWidth();
int height = bmp.getHeight();
Bitmap.Config config = bmp.getConfig();
mBitmap = Bitmap.createBitmap(width, height, config);
mBitmapOptions = new BitmapFactory.Options();
//设置Bitmap内存复用
mBitmapOptions.inBitmap = mBitmap;//Bitmap复用内存块,类似对象池,避免不必要的内存分配和回收
mBitmapOptions.inMutable = true;//解码时返回可变Bitmap
mBitmapOptions.inSampleSize = 1;//缩放比例
}
}
//循环读取下一帧
private int getNext() {
mIndex++;
if (mIndex<mFrames.length){
return mFrames[mIndex];
}else if (mIndex >= mFrames.length && isLoop) {
return mIndex = 0;
} else{
stop();
return mIndex = 0;
}
}
/**
* 播放动画,同步锁防止多线程读帧时,数据安全问题
*/
public synchronized void start() {
mShouldRun = true;
if (mIsRunning)
return;
Runnable runnable = new Runnable() {
@Override
public void run() {
ImageView imageView = mSoftReferenceImageView.get();
if (!mShouldRun || imageView == null) {
mIsRunning = false;
if (mOnAnimationStoppedListener != null) {
mOnAnimationStoppedListener.AnimationStopped();
}
return;
}
mIsRunning = true;
//新开线程去读下一帧
mHandler.postDelayed(this, mDelayMillis);
if (imageView.isShown()) {
int imageRes = getNext();
if (mBitmap != null) { // so Build.VERSION.SDK_INT >= 11
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeResource(imageView.getResources(), imageRes, mBitmapOptions);
} catch (Exception e) {
e.printStackTrace();
}
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
} else {
imageView.setImageResource(imageRes);
mBitmap.recycle();
mBitmap = null;
}
} else {
imageView.setImageResource(imageRes);
}
}
}
};
mHandler.post(runnable);
}
/**
* 停止播放
*/
public synchronized void stop() {
mShouldRun = false;
}
public synchronized void loop(boolean isLoop) {
this.isLoop = isLoop;
}
/**
* 设置停止播放监听
*
* @param listener
*/
public void setOnAnimStopListener(OnAnimationStoppedListener listener) {
this.mOnAnimationStoppedListener = listener;
}
}
/**
* 停止播放监听
*/
public interface OnAnimationStoppedListener {
void AnimationStopped();
}
}
上一篇: matplotlib嵌入pyqt5绘制2D、3D图
下一篇: 数据结构知识点整理