Skip to content

Instantly share code, notes, and snippets.

@zty5678
Created May 30, 2023 02:43
Show Gist options
  • Save zty5678/91296c576579e5694d1d93be2aac30f4 to your computer and use it in GitHub Desktop.
Save zty5678/91296c576579e5694d1d93be2aac30f4 to your computer and use it in GitHub Desktop.
UIJobScheduler: 记录当前一帧进行的操作所花费的时间,如果不够进行下一个操作,则将下一个操作放到下一帧,以此来增加画面的流畅度。
import android.os.Handler;
import android.view.Choreographer;
import java.util.ArrayDeque;
import java.util.concurrent.Callable;
public class UIJobScheduler {
private final static float MAX_JOB_TIMES_MS = 4f;
private static long elapsed = 0L;
private static ArrayDeque<Callable> jobQueue = new ArrayDeque<>();
private static Handler handler = new Handler();
private static boolean isOverMaxtime() {
return elapsed > MAX_JOB_TIMES_MS * 1_000_000;
}
public static void submitJob(final Callable job) {
jobQueue.add(job);
if (jobQueue.size() == 1) {
handler.post(new Runnable() {
@Override
public void run() {
processJobs();
}
});
}
}
private static void processJobs() {
while (!jobQueue.isEmpty() && !isOverMaxtime()) {
long start = System.nanoTime();
Callable currentJob = jobQueue.poll();
if (currentJob != null) {
try {
currentJob.call();
} catch (Exception e) {
e.printStackTrace();
}
}
elapsed += System.nanoTime() - start;
}
if (jobQueue.isEmpty()) {
elapsed = 0;
} else {
onNextFrame(new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
elapsed = 0;
processJobs();
}
});
}
}
private static void onNextFrame(Choreographer.FrameCallback callback) {
Choreographer.getInstance().postFrameCallback(callback);
}
}
object UIJobScheduler {
private const val MAX_JOB_TIME_MS: Float = 4f
private var elapsed = 0L
private val jobQueue = ArrayDeque<() -> Unit>()
private val isOverMaxTime get() = elapsed > MAX_JOB_TIME_MS * 1_000_000
private val handler = Handler()
fun submitJob(job: () -> Unit) {
jobQueue.add(job)
if (jobQueue.size == 1) {
handler.post { processJobs() }
}
}
private fun processJobs() {
while (!jobQueue.isEmpty() && !isOverMaxTime) {
val start = System.nanoTime()
jobQueue.poll().invoke()
elapsed += System.nanoTime() - start
}
if (jobQueue.isEmpty()) {
elapsed = 0
} else if (isOverMaxTime) {
onNextFrame {
elapsed = 0
processJobs()
}
}
}
private fun onNextFrame(callback: () -> Unit) =
Choreographer.getInstance().postFrameCallback { callback() }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment