2

If I click multiple times on a button in a short time, sometimes the action gets executed multiple times (Depends on the click speed), is there a way to prevent this by using anything integrated into ButterKnife?

After searching on google looking for a solution to that problem, I came through a SO post asking the same https://stackoverflow.com/a/38525054/7575454 after that, I tried digging a bit on the ButterKnife source code and found the class named DebouncingOnClickListener (Mostly looked on this class because the class "layout" was similar to a solution I found on StackOverflow).

There is a comment on that class that says

A click on one button disables all buttons for that frame

If I understand correctly, that means I shouldn't be able to "spam" click on my button. But it's not the case since I'm able to perform the action button multiple times if I spam click said button.

The solution I found on StackOverflow "fixes" my problem but I was just wondering if there was anything else similar to this on ButterKnife (Appart for the class that I said early) since I don't really want to do a mess on my source code setting the click listeners "manually" for a couple of buttons and use @OnClick on the ones I don't really care if there are called multiple times.

Marzi Heidari
  • 2,660
  • 4
  • 25
  • 57

3 Answers3

5

The DebouncingOnClickListener prevents multiple clicks in one frame. That's not a long delay, only a few milliseconds. As you can read as a comment to an issue, Jake Wharton (the author) considers this behavior as part of the application layer, which he doesn't want to add to Butter Knife.

It only debounces two clicks on one frame. If you click twice on two separate frames then that's the responsibility of the application layer to handle. You can fix this by disabling the button on the first click.

Or you have your application or domain implementing a time based debounce (depending on your use-case).

tynn
  • 38,113
  • 8
  • 108
  • 143
0

I use the solution you attached. I save on a variable the time when a button is clicked and make sure this time is equal or greater than 250ms. This works fine but I agree that would be nice to have ButterKnife control this automatically defining the time frame you want between clicks. This option is also good because not only make sure one button is not clicked multiple times, but you can use the same variable for every button in the same activity.

Another option would be to disable the button clicked and enable it back again once the action triggered by this button is finished.

0

Add the following class to your project, and rebuild your project, the problem will be resolved.

package butterknife.internal;

import android.support.annotation.NonNull;
import android.view.View;

public abstract class DebouncingOnClickListener implements View.OnClickListener {
    static boolean enabled = true;

    public final String name = "MyDebouncingOnClickListener";

    private static final Runnable ENABLE_AGAIN = new Runnable() {
        @Override public void run() {
            enabled = true;
        }
    };

    @Override public final void onClick(View v) {
        if (enabled) {
            enabled = false;
            // v.post(ENABLE_AGAIN); !!!The modified code is here!!!!
            v.postDelayed(ENABLE_AGAIN, 300);
            doClick(v);
        }
    }

    public abstract void doClick(View v);

    @NonNull
    @Override
    public String toString() {
        return super.toString();
    }
}