bhowell2/debouncer


Multi-feature java debouncer.

License: MIT

Language: Java

Keywords: java, utilities


codecov

Debouncer

A multi-feature debouncer for Java projects, allowing to debounce immediately (i.e., run the event immediately and then no future events until the debounce interval expires), on the first event (when the debounce interval expires), the last event, or even debounce immediately and on the most recent event. This also provides a forced-timeout feature so that an event will not be debounced indefinitely.

Requirements

Requires Java 1.8+, because of lambda use. There are no external dependencies.

Install

This can be obtained from the Maven Central repository:

Maven

<dependency>
    <groupId>io.github.bhowell2</groupId>
    <artifactId>debouncer</artifactId>
    <version>1.0.0</version>
</dependency>

Gradle

dependencies {
    compile "io.github.bhowell2:debouncer:1.0.0"
}

Usage

It should be noted that if a forced-timeout is not supplied an event could be debounced indefinitely (examples below), because every time an event is received, the debounce interval is extended. All callbacks are run on the debouncer's executor service thread, so they should not be long running as that would block other callbacks from being run and could even block your calling thread to add another event

  • ideally the user will call another thread to run the callback's actual code.

In most cases the user will always call the same debounce type (e.g. run-first or run-last) in the same place, but this is not a strict requirement and the user could call addRunLast("key", k -> {}) then addRunFirst(...) which would reset the debounce interval, but still call the run last callback (see below for more information on this behavior).

For the examples below assume threads sleep for the exact amount of time. This, of course, is never really the case and threads will sleep for a minimum of the sleep time, but due to scheduling they will not kick back in till some time after the specified sleep time.

Tasks

These are created for each key supplied to the debouncer. A task is active until the debounce interval or the forced-timeout has expired and the task's callback has been run. The next call for the same key will create a new task. A task's timeout and forced-timeout cannot be changed once it is created and subsequent attempts to debounce an event for a given key will extend the debounce interval by the initial timeout amount. The forced-timeout will never be changed from the event's initial creation. The callback will be changed if a subsequent call of type run-last is made while a task is active.

Subsequent calls for the same key while a task is still active will ALWAYS extend expiration time.

Run Immediately

This will immediately run the callback and will not allow any other callbacks for the given event key to run until the debounce interval has expired.

Calls after runImmediately (while task is active): runImmediately - will not run anything because a task is active runFirst - will not run anything, because a task is active. runLast - will run the last runLast's callback when the interval expires

Debouncer debouncer = new Debouncer(1);
debouncer.addRunImmediately(10, TimeUnit.MILLISECONDS, "key", k -> {
  System.out.println("This prints immediately.");
});
debouncer.addRunImmediately(10, TimeUnit.MILLISECONDS, "key", k -> {
  System.out.println("This will not print at all if submitted within 10ms.");
});

Run First

This will run the first callback for the given event key when the debounce interval expires.

Calls after runFirst (while task is active): runImmediately - will not run anything because a task is active runFirst - will not run anything, because a task is active. runLast - will run the last runLast's callback when the interval expires, discarding the initial runFirst callback

Debouncer debouncer = new Debouncer(1);
debouncer.addRunFirst(10, TimeUnit.MILLISECONDS, "key", k -> {
  System.out.println("This prints when the debounce interval expires. Any other " +
   "events added for the same key will not be run until this expires. So long as " +
   "addRunFirst() or addRunImmediately() is used, this will not be overridden. " +
   "However, this will be overridden if addRunLast() is used before the " +
   "debounce interval expires.");
});
Thread.sleep(5);
/*
This will not extend the debounce interval by 15ms, but only by 10, the original 
interval set above.
*/
debouncer.addRunFirst(15, TimeUnit.MILLISECONDS, "key", k -> {
  System.out.println("This will not print at all if submitted within 10ms.");
});

Run Last

This will run the last callback for the given event key when the debounce interval expires.

Calls after runFirst (while task is active): runImmediately - will not run anything because a task is active runFirst - will not run anything, because a task is active. runLast - will discard the most recent callback and override with the latest

Debouncer debouncer = new Debouncer(1);
debouncer.addRunLast(10, TimeUnit.MILLISECONDS, "key", k -> {
  System.out.println("This will only be run if addRunLast() is called again before " +
   "the debounce interval expires.");
});
Thread.sleep(5);
/*
This will not extend the debounce interval by 15ms, but only by 10, the original 
interval set above.
*/
debouncer.addRunLast(15, TimeUnit.MILLISECONDS, "key", k -> {
  System.out.println("This will print in 10ms. Note, it is not after 15ms.");
});

Run Immediately and Run Last (runImmediatelyAndRunLast)

This is provided out of convenience so the user can always make the same call and does not have to make conditional calls. It would be the same as calling runImmediately and then when another task for the given event arrives calling runLast, but avoids the user having to keep track of whether or not they need to call runImmediately or runLast.

Debouncer debouncer = new Debouncer(1);
debouncer.addRunImmediatelyAndRunLast(10, TimeUnit.MILLISECONDS, "key", k -> {
  System.out.println("This is called immediately. If no other events for the " +
   "key are submitted nothing is run again.");
});
// if another event is submitted, the last callback will be run
debouncer.addRunImmediatelyAndRunLast(10, TimeUnit.MILLISECONDS, "key", k -> {
  System.out.println("This is not run, because overridden below.");
});
debouncer.addRunImmediatelyAndRunLast(10, TimeUnit.MILLISECONDS, "key", k -> {
  System.out.println("This is run 10ms from now.");
});

Note there is not a runImmediatelyAndRunFirst, because runFirst never overrides the callback for an active task.

Project Statistics

Sourcerank 3
Repository Size 0 Bytes
Stars 0
Forks 0
Watchers 1
Open issues 0
Dependencies 0
Contributors 1
Tags 1
Created
Last updated
Last pushed

Top Contributors See all

Blake

Recent Tags See all

1.0.0-release November 20, 2019

Something wrong with this page? Make a suggestion

Last synced: 2019-11-20 20:12:32 UTC

Login to resync this repository