This is the fourth day of my participation in the August More text Challenge. For details, see:August is more challenging

preface

In Android interface development, frequent action is a point of concern. Frequent operations: Collisions caused by clicking a button too often, or clicking multiple items at the same time.

The solution

Scenario 1

Suppose there is A button T on the Activiyt A interface. Click T to jump to Activity B.

void handleClick(a){
    Intent intent = new Intent(ActivityA.this,ActivityB.class);
    startActivity(intent);
}
Copy the code

But the user is likely to click twice in a row, and ActivityB will launch twice (in STANDARD launch mode in B), and the user will have to hit the back key to get back to ActivityA, which is not a particularly good experience. Presumably many small partners have encountered, the solution is to judge by time, in a certain period of time to prohibit the operation. But you can’t write down the time in every method. Such as this

long lastTime = 0;
void handleClick(a){
    long currentTime = System.currentTimeMillis();
    if ( currentTime - lastTime < 200) {return;
    }
    // The specific operation. }Copy the code

This common method, naturally is to abstract a class out.

public class OperateLock {
    private final static long DEFAULT_PERIOD = 200;
    private final long period;
    private long lastOperatorTime = 0;
    public OperateLock(a) {
        period = DEFAULT_PERIOD;
    }
    public OperateLock(int minimumPeriod) {
        period = minimumPeriod;
    }
    public boolean doing(a) {
        boolean doing = false;
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastOperatorTime > period) {
            lastOperatorTime = currentTime;
            doing = true;
        }
        return doing;
    }
    public boolean doing(int minimumPeriod) {
        boolean doing = false;
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastOperatorTime > minimumPeriod) {
            lastOperatorTime = currentTime;
            doing = true;
        }
        returndoing; }}Copy the code

In the code above, you can change it to

private OperateLock operateLock = new OperateLock();
void handleClick(a){
    if(! operateLock.doing())return;
    // The specific operation. }Copy the code

However, in the case of many buttons in the above code, it is obviously too much to write many operate objects. So, let’s continue to modify the code

public class ObjectOperateLock {
    private final static long DEFAULT_PERIOD = 200;
    private final long period;
    private long lastOperatorTime = 0;
    private List< WeakReference > operateObjList = new LinkedList<>();
    private HashMap< WeakReference, Long > timeHashMap = new HashMap<>();
    public ObjectOperateLock(a) {
        period = DEFAULT_PERIOD;
        Object obj = new Object();
    }
    public ObjectOperateLock(int minimumPeriod) {
        period = minimumPeriod;
    }
    public boolean doing(Object obj) {
        doing(obj, period);
    }
    public boolean doing(Object obj, long minimumPeriod) {
        boolean doing = false;
        long lastOperateTime = 0;
        WeakReference wk = null;
        Iterator< WeakReference > iterator = operateObjList.iterator();
        while (iterator.hasNext()) {
            WeakReference w = iterator.next();
            if (w.get() == null) {
                iterator.remove();
                timeHashMap.remove(w);
            } else if(w.get() == obj) { wk = w; }}if (wk == null) {
            wk = new WeakReference(obj);
            operateObjList.add(wk);
            timeHashMap.put(wk, 0L);
            doing = true;
        } else {
            long cur = System.currentTimeMillis();
            lastOperateTime = timeHashMap.get(wk);
            if (cur - lastOperateTime > minimumPeriod) {
                doing = true; lastOperateTime = cur; timeHashMap.put(wk, lastOperateTime); }}returndoing; }}Copy the code

Intercepting frequent clicks code changed to:

private ObjectOperateLock operateLock = new ObjectOperateLock();
void handleClickButton1(View v){
    if(! operateLock.doing(v))return;
    // The specific operation. }void handleClickButton2(View v){
    if(! operateLock.doing(v))return;
    // The specific operation. }Copy the code

Of course, all methods in ObjectOperateLock could be static as well, but that would be bad for setting a default period. For example, some buttons might be clicked once for 200 milliseconds or less, while other views might be clicked once for 500 milliseconds. ObjectOperateLock = OperateLock; ObjectOperateLock = OperateLock;

Scenario 2

There is a RecyclerView, which has a pile of item,item click will jump into a page,item carrying data is different, that how to intercept the item frequently click it.

In this scenario, in contrast to Scenario 1, there is a problem where two items are clicked at the same time. In this case, you can use OperateLock.

private OperateLock operateLock = new OperateLock();
void handleItemClick(View v){
    if(! operateLock.doing())return;
}
Copy the code

conclusion

Not only the button click event, but also other frequent operations need to set a specified time not to repeat the operation, so encounter these interception frequent operations, according to the need to write an interception class.