使用方式和解析链接:https://blog.youkuaiyun.com/humorousz/article/details/79552641
播放GIF偶尔出现频繁播、帧与帧之间的播放时长和实际的不同,原因是因为mLastSwap的使用
来看看mLastSwap的赋值代码:
@Override
public void draw(Canvas canvas) {
synchronized (mLock) {
checkDestroyedLocked();
if (mState == STATE_WAITING_TO_SWAP) {
// may have failed to schedule mark ready runnable,
// so go ahead and swap if swapping is due
if (mNextSwap - SystemClock.uptimeMillis() <= 0) {
mState = STATE_READY_TO_SWAP;
}
}
if (isRunning() && mState == STATE_READY_TO_SWAP) {
// Because draw has occurred, the view system is guaranteed to no longer hold a
// reference to the old mFrontBitmap, so we now use it to produce the next frame
Bitmap tmp = mBackBitmap;
mBackBitmap = mFrontBitmap;
mFrontBitmap = tmp;
BitmapShader tmpShader = mBackBitmapShader;
mBackBitmapShader = mFrontBitmapShader;
mFrontBitmapShader = tmpShader;
mLastSwap = SystemClock.uptimeMillis();
boolean continueLooping = true;
if (mNextFrameToDecode == mFrameSequence.getFrameCount() - 1) {
mCurrentLoop++;
if ((mLoopBehavior == LOOP_FINITE && mCurrentLoop == mLoopCount) ||
(mLoopBehavior == LOOP_DEFAULT && mCurrentLoop == mFrameSequence.getDefaultLoopCount())) {
continueLooping = false;
}
}
if (continueLooping) {
scheduleDecodeLocked();
} else {
scheduleSelf(mFinishedCallbackRunnable, 0);
}
}
}
这里的mLastSwap是获取SystemClock.uptimeMillis() 来实现,在赋值前还有其他代码在执行,那么就有可能每次播放获取回来的值都不一定相等,从而导致统计帧与帧之间的时长不准确
原代码:
//计算是否满足交换普片的条件
synchronized (mLock) {
if (mDestroyed) {
bitmapToRelease = mBackBitmap;
mBackBitmap = null;
} else if (mNextFrameToDecode >= 0 && mState == STATE_DECODING) {
schedule = true;
//计算下次调度的时间,上一张图片的展示时间加上上次调度的时间(mLastSwap就是上次调度的时间)
mNextSwap = exceptionDuringDecode ? Long.MAX_VALUE : invalidateTimeMs + mLastSwap;
mState = STATE_WAITING_TO_SWAP;
}
}
修改后代码:
//计算是否满足交换普片的条件
synchronized (mLock) {
if (mDestroyed) {
bitmapToRelease = mBackBitmap;
mBackBitmap = null;
} else if (mNextFrameToDecode >= 0 && mState == STATE_DECODING) {
schedule = true;
//计算下次调度的时间,上一张图片的展示时间+上次调度的时间+代码执行时间(SystemClock.uptimeMillis()就是上次调度的时间加代码执行时间)
mNextSwap = exceptionDuringDecode ? Long.MAX_VALUE : invalidateTimeMs + SystemClock.uptimeMillis();
mState = STATE_WAITING_TO_SWAP;
}
}