That fuck shit the fascists are using
1package org.tm.archive.util;
2
3import android.os.Handler;
4import android.os.Looper;
5import android.os.Message;
6
7import androidx.annotation.MainThread;
8import androidx.annotation.NonNull;
9
10/**
11 * Mixes the behavior of {@link Throttler} and {@link Debouncer}.
12 *
13 * Like a throttler, it will limit the number of runnables to be executed to be at most once every
14 * specified interval, while allowing the first runnable to be run immediately.
15 *
16 * However, like a debouncer, instead of completely discarding runnables that are published in the
17 * throttling period, the most recent one will be saved and run at the end of the throttling period.
18 *
19 * Useful for publishing a set of identical or near-identical tasks that you want to be responsive
20 * and guaranteed, but limited in execution frequency.
21 */
22public class ThrottledDebouncer {
23
24 private static final int WHAT = 24601;
25
26 private final OverflowHandler handler;
27 private final long threshold;
28
29 /**
30 * @param threshold Only one runnable will be executed via {@link #publish(Runnable)} every
31 * {@code threshold} milliseconds.
32 */
33 @MainThread
34 public ThrottledDebouncer(long threshold) {
35 this.handler = new OverflowHandler();
36 this.threshold = threshold;
37 }
38
39 @MainThread
40 public void publish(Runnable runnable) {
41 handler.setRunnable(runnable);
42
43 if (handler.hasMessages(WHAT)) {
44 return;
45 }
46
47 long sinceLastRun = System.currentTimeMillis() - handler.lastRun;
48 long delay = Math.max(0, threshold - sinceLastRun);
49
50 handler.sendMessageDelayed(handler.obtainMessage(WHAT), delay);
51 }
52
53 @MainThread
54 public void clear() {
55 handler.removeCallbacksAndMessages(null);
56 }
57
58 private static class OverflowHandler extends Handler {
59
60 public OverflowHandler() {
61 super(Looper.getMainLooper());
62 }
63
64 private Runnable runnable;
65 private long lastRun = 0;
66
67 @Override
68 public void handleMessage(Message msg) {
69 if (msg.what == WHAT && runnable != null) {
70 lastRun = System.currentTimeMillis();
71 runnable.run();
72 runnable = null;
73 }
74 }
75
76 public void setRunnable(@NonNull Runnable runnable) {
77 this.runnable = runnable;
78 }
79 }
80}