3

On activity A I have a button named btnA which will show an activity B whenever it is clicked.

But if I click on this btnA button too fast like 2 clicks within a second then 2 activity B will be shown. Obviously.

I know the solution for this is debouncing the on click listener of btnA using RxBinding or Kotlin coroutine...

But what if a have 100 views which all behave just like btnA in my app. How can I somehow override or intercept their on click listener to apply debouncing in one place?

Edit: I'm using Kotlin which mean I can add an extension function to apply the debounce logic over View's on click listener but that won't work if the click event handler is bound by ButterKnife or other alternatives library. That why I'm finding a way to override or intercept the View's click listener.

Also, creating some sort of root View/ base View which all app's View will extend from might be overkill, I think.

This might be impossible at the moment but somehow I have an urge that there is a solution somewhere out there.

Harvey
  • 1,353
  • 1
  • 14
  • 27
  • you can make a method which will have an onClickListener of a view or a button. And pass that method with a view/button. In that way you will have a single method and it can be used in all your application. But the problem will arise when every button will have a different working mechanism. :) – Umair May 09 '19 at 04:56
  • Check out this post: https://stackoverflow.com/questions/25905086/multiple-buttons-onclicklistener-android – Amit May 09 '19 at 04:57
  • @Umair - your solution might not work if I used some sort of event handler binding library like ButterKnife. – Harvey May 09 '19 at 05:02
  • @Amit - Thanks but implementing on click in activity it is not what Am I looking for. Let say I want all my view in my application to debounce its on click for 1 sec on its own. – Harvey May 09 '19 at 05:06
  • @HauLuu You can create custom click listener class which will implement View.OnClickListener and you can put you logic inside this and set this listener for all the view. Then you will receive call back in this call which will be independent from activity/fragment. – Amit May 09 '19 at 06:13
  • Right now, the only solution is create a debounced listener as point out in https://stackoverflow.com/questions/16534369/avoid-button-multiple-rapid-clicks. Then using it instead of `View.OnClickListener`. – Son Truong May 09 '19 at 06:41

2 Answers2

1

I do not know of any way to globally override all click listeners. Likely, this is not possible. But if you use Kotlin, you could do something like this:

fun View.onClickThrottled(skipDurationMillis: Long = 750, action: () -> Unit) {
  var isEnabled = true
  this.setOnClickListener {
    if (isEnabled) {
      action()
      isEnabled = false
      Handler().postDelayed({ isEnabled = true }, skipDurationMillis)
    }
  }
}

And then, change your views to use this instead, like this:

button.onClickThrottled {
   //TODO - do something
}
EAlgekrans
  • 121
  • 3
  • Yeah! this is my original solution (not exactly in code but do share the same idea) but the problem is this won't work if I use ButterKnife to bind the click event handler to views. That is why I finding a way to override the view click event itself – Harvey May 09 '19 at 06:49
  • Wich is the diference between use "Handler().postDelayed(...)" and "postDelayed(...)" directly . there are not merory leaks in any of these cases? – Gilberto Ibarra Aug 06 '19 at 16:47
0

You can have your custom click listener which will implement View.OnClickListener, additionally you can pass a callback to your activity/fragment using your Fragment_ActivityListener. Fragment_ActivityListener is a interface which your activity/fragment receive it back from OnClickListener after debounce or logic performed.

 private class CustomClickListener implements View.OnClickListener {
   Fragment_ActivityListener listener;

   CustomClickListener(Fragment_ActivityListener listener){
       this.listener = listener;
   }

    @Override
    public void onClick(View view) {
          //Custom logic for debounce & call activity or fragment listener
        }
    }
}

call this in yourFragment or Activity like this

 btnNext.setOnClickListener(new CustomClickListener(this));

'this' implement Fragment_ActivityListener if required otherwise you can remove it.

Amit
  • 235
  • 3
  • 11