Butterknife @OnClick - 多次触发动作

Butterknife @OnClick - action triggered multiple times

如果我在短时间内多次点击一个按钮,有时操作会被执行多次(取决于点击速度),有没有办法通过使用集成到 ButterKnife 中的任何东西来防止这种情况发生?

在 google 上搜索该问题的解决方案后,我通过 SO post 询问了相同的 之后,我尝试在 ButterKnife 源代码并找到了名为 DebouncingOnClickListener 的 class (主要是看这个 class 因为 class "layout" 与我在Whosebug).

class 上有一条评论说

A click on one button disables all buttons for that frame

如果我没理解错的话,那意味着我不应该 "spam" 点击我的按钮。但事实并非如此,因为如果我垃圾邮件单击所述按钮,我可以多次执行操作按钮。

我在 Whosebug 上找到的解决方案 "fixes" 我的问题,但我只是想知道 ButterKnife 上是否还有其他类似的东西(我之前说过的 class 的 Appart)因为我不知道我真的不想把我的源代码搞得一团糟,为几个按钮设置点击侦听器 "manually",并在我不关心是否多次调用的按钮上使用 @OnClick

我使用你附上的解决方案。我将单击按钮的时间保存在变量上,并确保该时间等于或大于 250 毫秒。这工作正常,但我同意让 ButterKnife 控制它自动定义您想要的点击之间的时间范围会很好。 此选项也很好,因为不仅可以确保一个按钮不会被多次单击,而且您可以为同一 activity.

中的每个按钮使用相同的变量

另一种选择是禁用单击的按钮,并在此按钮触发的操作完成后再次启用它。

DebouncingOnClickListener 防止在一帧中多次点击。那不是很长的延迟,只有几毫秒。您可以阅读对 issue 的评论,Jake Wharton(作者)将此行为视为应用层的一部分,他不想将其添加到 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.

或者您的应用程序或域实现了基于时间的去抖动(取决于您的用例)。

将以下class添加到您的项目中,并重新构建您的项目,问题将得到解决。

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();
    }
}