「安卓开发」Android防爆力点击事件处理解决方法及其存在的问题

  Android中防爆力点击很多App中都会用到,但是我看过几个项目中的源码,大部分都是使用的System.currentTimeMillis()来获取当前时间与上一次点击时间间隔来做防暴力点击处理。
  但是问题来了,由于System.currentTimeMillis()获取的是系统时间,这个时间会根据手机设置的时间而变化,那么就会导致一种情况,即当用户点击了一个View后记录了上一次的点击时间戳,这时将时间往前调之后,下一次再点击时System.currentTimeMillis()获取到的时间戳是比上一次点击时间戳要小的,因此就会导致点击无响应的情况发生。虽然说,这种情况几乎不会发生,或者发生了影响也不会太大,但是既然是一个问题,并且可以找到其他解决的方法,那么为什么不使用更优的方式来计算处理点击事件的时间间隔呢。
  如下的代码中使用到了几种计算点击事件时间间隔的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package org.devlang.demo.click;

import android.os.SystemClock;
import android.util.Log;
import android.view.View;

import java.util.Calendar;

public abstract class OnThrottleClickListener implements View.OnClickListener {
private static final int THROTTLE_CLICK_GAP_TIME = 300;
private long preClickTime;

@Override
public void onClick(View view) {
// long currentTimeMillis = System.currentTimeMillis();
// long currentTimeMillis = Calendar.getInstance().getTimeInMillis();
long currentTimeMillis = SystemClock.uptimeMillis();
// long currentTimeMillis = SystemClock.elapsedRealtime();
if (currentTimeMillis - preClickTime > THROTTLE_CLICK_GAP_TIME) {
onThrottleClick(view);
preClickTime = currentTimeMillis;
Log.d("cmf", "perform");
} else {
Log.d("cmf", "break");
}
}

public abstract void onThrottleClick(View view);
}
  • System.currentTimeMillis() 系统时间,会根据手机系统中设置的时间改变;
  • Calendar.getInstance().getTimeInMillis() 这种方式是最low的。因为每次点击都会创建一个Calendar实例,在后端开发中,都是拒绝使用这个类的,因为效率会比较低。
  • SystemClock.uptimeMillis() 自开机后,经过的时间,不包括深度睡眠的时间。Looper中所使用的也是这个方法,对时间间隔的计算比较有保证。
  • SystemClock.elapsedRealtime() 自开机后,经过的时间,包括深度睡眠的时间。

  这也是之前开发中遇到的问题,虽然影响不大,但也可以注意一下这个问题。