在安卓系统中防止双击按钮的最佳方法是什么?
当前回答
当UI线程阻塞时,单击事件队列。对于按钮单击事件,请尽快将其更改为后台任务,以避免单击事件在彼此后面排队。
在activity类中声明一个volatile boolean或lock:
private volatile boolean saving = false;
创建一个onClickListener按钮,通过保存和启动一个后台任务来完成工作:
saveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!saving) {
saving = true;
new SaveAsyncTask().execute();
}
}
});
创建一个内部的SaveAsyncTask类来在后台完成工作:
class SaveAsyncTask extends AsyncTask {
@Override
protected Object doInBackground(Object[] objects) {
// Do something here, simulate a 3 second task
SystemClock.sleep(3000);
saving = false;
return null;
}
}
其他回答
对于任何使用数据绑定的用户:
@BindingAdapter("onClickWithDebounce")
fun onClickWithDebounce(view: View, listener: android.view.View.OnClickListener) {
view.setClickWithDebounce {
listener.onClick(view)
}
}
object LastClickTimeSingleton {
var lastClickTime: Long = 0
}
fun View.setClickWithDebounce(action: () -> Unit) {
setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View) {
if (SystemClock.elapsedRealtime() - LastClickTimeSingleton.lastClickTime < 500L) return
else action()
LastClickTimeSingleton.lastClickTime = SystemClock.elapsedRealtime()
}
})
}
<androidx.appcompat.widget.AppCompatButton
..
android:text="@string/signup_signin"
app:onClickWithDebounce="@{() -> viewModel.onSignUpClicked()}"
... />
使用setEnabled(false)禁用按钮,直到用户可以安全地再次单击它。
KLEANEST Kotlin惯用方式:
class OnSingleClickListener(private val block: () -> Unit) : View.OnClickListener {
private var lastClickTime = 0L
override fun onClick(view: View) {
if (SystemClock.elapsedRealtime() - lastClickTime < 1000) {
return
}
lastClickTime = SystemClock.elapsedRealtime()
block()
}
}
fun View.setOnSingleClickListener(block: () -> Unit) {
setOnClickListener(OnSingleClickListener(block))
}
用法:
button.setOnSingleClickListener { ... }
或者加上一个控制油门的附加参数
class OnClickListenerThrottled(private val block: () -> Unit, private val wait: Long) : View.OnClickListener {
private var lastClickTime = 0L
override fun onClick(view: View) {
if (SystemClock.elapsedRealtime() - lastClickTime < wait) {
return
}
lastClickTime = SystemClock.elapsedRealtime()
block()
}
}
/**
* A throttled click listener that only invokes [block] at most once per every [wait] milliseconds.
*/
fun View.setOnClickListenerThrottled(wait: Long = 1000L, block: () -> Unit) {
setOnClickListener(OnClickListenerThrottled(block, wait))
}
Usages:
button.setOnClickListenerThrottled(2000L) { /** some action */}
or
button.setOnClickListenerThrottled { /** some action */}
更可取的解决方案是,
onclick(){
btn.setEnabled(false);
btn.setClickable(false);
//yourwork
myWork();
}
myWork(){
//your tasks.
btn.setEnabled(true);
btn.setClickable(true);
}
由于一个环节很容易被忽略,我不得不一遍又一遍地重复这个环节
我更喜欢使用信号量块。它是线程安全的,不仅可以用于按钮。
代码示例很简单:
private UtilsSemaphore buttonSemaphore = new UtilsSemaphore();
public void onClick(View view)
{
boolean isAllowed = buttonSemaphore.lock();
if(!isAllowed)
{
return;
}
final View clickedButton = view;
clickedButton.setEnabled(false);
/* some code */
buttonSemaphore.unlock();
clickedButton.setEnabled(true);
}
public class UtilsSemaphore {
public int counter = 0;
public boolean lock()
{
int counterValue = ++counter;
boolean isAllowed = counterValue < 2;
if(!isAllowed)
{
unlock();
}
return isAllowed;
}
public void unlock()
{
--counter;
}
}
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用
- 在Android Studio中创建aar文件