Created
July 28, 2017 03:25
-
-
Save wyon/2787ca6facd7c97d192b7f433330b77e to your computer and use it in GitHub Desktop.
帧分析工具类,一个打印帧率和丢帧情况log的工具类,原理是利用Choreographer的FrameCallback。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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