package com.test.util;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.util.Log;
import android.view.View;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class AnimUtilX {
private final static String TAG = "AnimUtilX";
private int[] resIdArr;
private int index;
private View view;
private int period;//动画间隔
private boolean isRepeatFlag = false;
private boolean isStartFlag = false;
private int tokenIndex = 0;
private static AtomicInteger sThreadNum = new AtomicInteger(0);
private static ThreadPoolExecutor sExecutor;
static {
ThreadFactory threadGroup = new ThreadFactory(){
@Override
public Thread newThread(@NonNull Runnable r) {
Thread thread = new Thread(r, "anim-thread-" + sThreadNum.getAndIncrement());
return thread;
}
};
sExecutor = new ThreadPoolExecutor(2,2, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(), threadGroup);
sExecutor.allowCoreThreadTimeOut(true);
}
public interface OnAnimEndListener {
public void onAnimEnd();
}
private AnimUtilX.OnAnimEndListener listener;
//播放完成监听
public void setOnAnimEndListener(AnimUtilX.OnAnimEndListener listener) {
this.listener = listener;
}
private final static int PLAYING_ANIM_MSG = 0;
private final static int GET_BITMAP_MSG = 1;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what) {
case PLAYING_ANIM_MSG: {
if (!(msg.obj instanceof TokenDelay)){
return;
}
TokenDelay tokenDelay = (TokenDelay) msg.obj;
if (tokenDelay.token != tokenIndex){
Log.e(TAG, "PLAYING_ANIM_MSG, msg.tokenIndex = " + tokenDelay.token
+ ", tokenIndex = " + tokenIndex + ", ignore !!! " + view);
return;
}
if (resIdArr.length <= index || !isStartFlag){
Log.e(TAG, "index = " + index + ", resIdArr.length = " + resIdArr.length
+ ", isStartFlag = " + isStartFlag + ", invalid ignore !!!");
return;
}
Task task = new Task.Builder()
.setResource(view.getResources())
.setResId(resIdArr[index])
.setHandler(handler)
.setMsgWhat(GET_BITMAP_MSG)
.setDelay(tokenDelay.delay)
.setTokenIndex(tokenDelay.token)
.create();
sExecutor.execute(task);
break;
}
case GET_BITMAP_MSG: {
if (isActivityFinish()){
Log.e(TAG, " Activity is Finish , ignore !!!! " + view);
return;
}
if (!isStartFlag) {
Log.e(TAG, "anim is stop *** " + view);
return;
}
if(msg.arg1 != tokenIndex){
Log.e(TAG, "msg tokenIndex " + tokenIndex
+ ", tokenIndex = " + tokenIndex + ", ignore !!! " + view);
return;
}
Bitmap bitmap = (Bitmap) msg.obj;
BitmapDrawable bd = new BitmapDrawable(view.getResources(), bitmap);
view.setBackground(bd);
index++;
if (index >= resIdArr.length) {
if (isRepeatFlag) {
index = 0;
} else {
if (listener != null) {
listener.onAnimEnd();
}
return;
}
}
sendPlayAnimMsg(period);
break;
}
}
}
};
public AnimUtilX() {
index = 0;//第几章图片
}
/**
* @param view 控件
* @param resIdArr 图片素材
* @param isRepeatFlag 是否循环播放
*/
public void setAnimInfo(View view, int[] resIdArr, boolean isRepeatFlag) {
this.view = view;
this.resIdArr = resIdArr;
this.isRepeatFlag = isRepeatFlag;
}
public void startAnim(int period){
startAnim(0, period);
}
/**
*
* @param delayMillis 延时
* @param period 一帧持续时间
*/
public void startAnim(long delayMillis, int period) {
if (delayMillis < 0){
delayMillis = 0;
}
this.period = period;
index = 0;
handler.removeMessages(PLAYING_ANIM_MSG);
sendPlayAnimMsg((int)delayMillis);
isStartFlag = true;
}
/**
* 是否正在播放
*
* @return
*/
public boolean isAniming() {
return isStartFlag;
}
//是否循环
public boolean isRepeat() {
return isRepeatFlag;
}
public void stopAnim() {
isStartFlag = false;
tokenIndex++;
if (handler.hasMessages(PLAYING_ANIM_MSG)) {
Log.i(TAG, "stopAnim() stopAnim hasMessages(PLAYING_ANIM_MSG) " + view);
}
handler.removeMessages(PLAYING_ANIM_MSG);
//view.setBackgroundResource(resIdArr[0]);
}
//应用退出
public static void quit() {
sExecutor.shutdownNow();
}
private boolean isActivityFinish(){
Context context = view.getContext();
if (context instanceof Activity){
Activity activity = (Activity) context;
if (activity.isFinishing() || activity.isDestroyed()){
return true;
}
}
return false;
}
static class TokenDelay{
final int token;
final int delay;
public TokenDelay(int token, int delay){
this.token = token;
this.delay = delay;
}
}
private void sendPlayAnimMsg(int delay){
Message sendMsg = Message.obtain(handler, PLAYING_ANIM_MSG, 0, 0);
sendMsg.obj = new TokenDelay(tokenIndex, delay);
handler.sendMessage(sendMsg);
}
static class Task implements Runnable {
final Resources resource;
final int resId;
final Handler handler;
final int msgWhat;
final int delay;
final long startTime;
final int tokenIndex;
public Task(Builder builder){
resource = builder.resource;
resId = builder.resId;
handler = builder.handler;
msgWhat = builder.msgWhat;
delay = builder.delay;
startTime = builder.startTime;
tokenIndex = builder.tokenIndex;
}
@Override
public void run() {
long time = System.currentTimeMillis();
Bitmap bitmap = BitmapFactory.decodeResource(resource, resId);
Log.i(TAG, "" + Thread.currentThread() + ", BitmapFactory.decodeResource use time "
+ (System.currentTimeMillis() - time));
long useTime = System.currentTimeMillis() - startTime;
long msgDelay = delay - useTime;
if (msgDelay < 0){
msgDelay = 0;
}
Message msg = Message.obtain();
msg.what = msgWhat;
msg.arg1 = tokenIndex;
msg.obj = bitmap;
handler.sendMessageDelayed(msg, msgDelay);
}
public static class Builder{
private Resources resource;
private int resId;
private Handler handler;
private int msgWhat;
private int delay;
private long startTime;
private int tokenIndex;
public Builder(){
}
public Builder setResource(Resources resource){
this.resource = resource;
return this;
}
public Builder setResId(int resId){
this.resId = resId;
return this;
}
public Builder setHandler(Handler handler){
this.handler = handler;
return this;
}
public Builder setMsgWhat(int msgWhat){
this.msgWhat = msgWhat;
return this;
}
public Builder setDelay(int delay){
this.delay = delay;
return this;
}
public Builder setTokenIndex(int index){
this.tokenIndex = index;
return this;
}
public Task create(){
startTime = System.currentTimeMillis();
return new Task(this);
}
}
}
}
|