Skip to content

Instantly share code, notes, and snippets.

@wyon
Created July 28, 2017 03:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wyon/2787ca6facd7c97d192b7f433330b77e to your computer and use it in GitHub Desktop.
Save wyon/2787ca6facd7c97d192b7f433330b77e to your computer and use it in GitHub Desktop.
帧分析工具类,一个打印帧率和丢帧情况log的工具类,原理是利用Choreographer的FrameCallback。
package com.wyon.util;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.Log;
import android.view.Choreographer;
/**
* 功能:分析丢帧情况和帧绘制耗时
* 描述:需要分析的代码前后加上 FrameAnalyze.start(), FrameAnalyze.stop()
* Created by wyon on 6/17/17.
*/
public class FrameAnalyze {
public static boolean start() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
SMFrameCallback.getInstance().mIsOpen = true;
SMFrameCallback.getInstance().lastFrameTimeNanos = 0;
SMFrameCallback.getInstance().postCallback();
return true;
}
return false;
}
public static void stop() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
SMFrameCallback.getInstance().stopInternal();
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
private static class SMFrameCallback implements Choreographer.FrameCallback {
private static final String TAG = "SMFrameCallback";
private static final float deviceRefreshRateMs = 16.6f;
private static SMFrameCallback sInstance;
private long lastFrameTimeNanos = 0;//纳秒为单位
private boolean mIsOpen;
private static SMFrameCallback getInstance() {
if (sInstance == null) {
sInstance = new SMFrameCallback();
}
return sInstance;
}
private void postCallback() {
if (mIsOpen) {
Choreographer.getInstance().postFrameCallback(this);
}
}
private void stopInternal() {
mIsOpen = false;
}
@Override
public void doFrame(long frameTimeNanos) {
if (lastFrameTimeNanos == 0) {
lastFrameTimeNanos = frameTimeNanos;
postCallback();
return;
}
float value = (frameTimeNanos - lastFrameTimeNanos) / 1000000.0f;
final int skipFrameCount = skipFrameCount(lastFrameTimeNanos, frameTimeNanos, deviceRefreshRateMs);
Log.e(TAG, "两次绘制时间间隔value=" + value + " skipFrameCount=" + skipFrameCount + " frameTimeNanos=" + frameTimeNanos + " currentFrameTimeNanos=" + frameTimeNanos + "");
lastFrameTimeNanos = frameTimeNanos;
postCallback();
}
/**
* 计算跳过多少帧
*
* @param start
* @param end
* @param devicefreshRate
* @return
*/
private int skipFrameCount(long start, long end, float devicefreshRate) {
int count = 0;
long diffNs = end - start;
long diffMs = Math.round(diffNs / 1000000.0f);
long dev = Math.round(devicefreshRate);
if (diffMs > dev) {
long skipCount = diffMs / dev;
count = (int) skipCount;
}
return count;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment