That fuck shit the fascists are using
at master 80 lines 2.2 kB view raw
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}