如果你非常快速点击2个单独的按钮,甚至是同一个按钮,Android将处理两个点击事件。当它可以启动服务两次,或者显示对话两次,或者开始相互之间的活动等时,这就成了一个问题。
防止单个按钮双击的修复非常简单,答案就是StackOverflow。您只需检查是否已使用布尔标志单击该按钮,并停止处理任何进一步的单击事件。
我的问题是用户可能会快速按两个(或更多)不同的按钮(或列表项,或ActionBar项等)。处理“有按钮x被点击 - >更好地禁用按钮x,y,z”的每个组合将是非常乏味和容易出错。
有没有人有一个像样的解决方案?
答案 0 :(得分:2)
我会投入我的.02,虽然这可能不适合作为一个体面的解决方案。它很简单,没有考虑到例如启用按钮,安排或任何其他复杂的操作。它可能会删除一些样板,例如禁用按钮,但需要付出丑陋try-finally
语法的代价:
public final class EventLocker {
private static Object lock;
public static synchronized boolean lock(final Object object) {
if (null == object) { throw new IllegalArgumentException("object must not be null"); }
if (null == lock) {
lock = object;
return true;
}
return false;
}
public static synchronized boolean release(final Object object) {
if (null != lock && lock.equals(object)) {
lock = null;
return true;
}
return false;
}
}
然后,假设您希望在按钮上设置OnClickListener:
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (EventLocker.lock(view)) {
try {
doSomething();
} finally {
EventLocker.release(view);
}
}
}
});
如果你一直使用锁定解锁习语,你可以保证例如按钮B释放锁定后,按钮B将不会执行任何操作。从好的方面来说,如果需要,可以很容易地添加自定义要求。
回答下面的第一条评论:
你是对的 - 在我的回答中没有特别提到这一点,我有点邋..
例如,每个onClick()
事件都会发布到主线程队列中。有趣的是,它提出了一个我不可避免地要避免的话题;如果顺序处理按钮点击事件并且不离开主线程,则例如双击不是异常,而是在短时间内一个接一个地处理两个有效的动作。
确实没有任何问题 - 短暂的150毫秒可能没有意义,但10秒可能是一个完全可行的选择。在这些情况下,我认为最好确保onClick
实现足够聪明,可以重用,重建或以任何其他方式处理手头的资源。
答案 1 :(得分:1)
如果你非常快速点击2个单独的按钮,甚至是同一个按钮,Android将处理两个点击事件。当它可以启动服务两次,或者显示对话两次,或者开始相互之间的活动等时,这就成了一个问题。
编写良好的用户界面是幂等的,通常是通过验证:
在某些情况下,开发人员不担心完全幂等,因为框架会处理它(例如,给定一个编写良好的onStartCommand()
方法,启动服务两次应该不是问题;你不能删除相同的_ID两次)。在某些情况下,开发人员不担心完全幂等,因为对用户的影响是非破坏性的(例如,开始两次活动)。在某些情况下,开发人员不担心这个问题,因为触发机制有效地阻止了重复的效果(例如,长按)。
在某些情况下,我们只是懒惰。 : - )
但验证应该是工作,而不是触发器。无论我们是否因按钮单击,操作项单击,列表行单击,设备震动,传入GCM消息等而启动服务,我们都需要确保以幂等方式处理工作。
我的问题是用户可能会快速按两个(或更多)不同的按钮(或列表项或ActionBar项等)。
这超越了幂等性。这也是不太可能的,因为用户只是不那么快地移动他们的手指 - 这是测试猴子将比普通人更多地遇到的事情。而且,AFAIK很少有开发人员担心的事情。
如果你真的想担心它,那么就拿出尽可能少的“担心”。例如,如果用户连续点击两个操作栏项,其中一个标记当前查看的详细信息作为收藏,另一个弹出对话框以允许用户将密码与当前查看的详细信息关联, 谁在乎?为什么这本质上无效?
但除此之外,是的,这将是乏味的。您需要跟踪所有可能的“不要快速连续执行此操作”并确定您是否在各种回调中遇到了“快速连续”案例(onClick()
,onListItemClick()
,onOptionsItemSelected()
)。许多代码可以被分解为某种EventMonitor
,它可以了解您的业务规则,并可以报告您是否遇到了快速连续的情况。