2

I have a case where when I press a button it communicates with a web service the problem I am having is if you double click that button it calls the web services twice causing a double submission. Any ideas how to prevent the button from accepting the second click? I looked at this post but it seems like the solution does not work.

Android Preventing Double Click On A Button

Community
  • 1
  • 1
EpicOfChaos
  • 822
  • 11
  • 23

4 Answers4

5

Disabling the button is not enough, you should also make the button unclickable with setClickable(false).

setEnabled() will only change the appearance of the button, which will continue to receive click events.

Dalmas
  • 26,409
  • 9
  • 67
  • 80
2

The best way in my opinion is to control when to run your web service. Set a boolean for your web service communication. Something like this (in pseudo-code. Don't remember android much)

private boolean webServiced = false;

public synchronized void startWebService(){
    if (!webServiced){
        webServiced = true;
        //run your web service call on separate thread or something
    }
}

public synchronized void onWebServiceDone(){
    webServiced = false;
    myButton.setClickable(true)
}

public void onButtonClick(Event e){
    startWebService();
    myButton.setClickable(false)
}

Whats important here is that the webService methods need to be synchronized that way you can ensure only one thread is accessing the webServiced boolean at a time. With this, even if a user manages to click the button multiple times before the setClickable(false) kicks in, your web service will still only be ran once.

Skyd
  • 411
  • 4
  • 11
1

This is a generic solution that you can use for your specific case and elsewhere in your code on any button, even if the event is an async call.

Then for your webservice endpoints, when you get a reply, timeout or the like, call the runnable passed, this will reset your button to being clickable once more. See class below:

public abstract class OneClickListener implements View.OnClickListener {

private boolean clickable = true;
private Runnable reactivateButtonRunnable;

@Override
public final void onClick(final View v) {
    if (clickable) {
        clickable = false;
        reactivateButtonRunnable = new Runnable() {
            @Override
            public void run() {
                reset();
            }
        };
        onOneClick(v, reactivateButtonRunnable);
    }
}

public abstract void onOneClick(View v, final Runnable reactivateButtonRunnable);

// reset listener to accept new clicks
public void reset() {
    clickable = true;
}
}

example pseudo-code, just to show the principle:

Button button = new Button(this);
button.setOnClickListener(new OneClickListener() {
        @Override
        public void onOneClick(View v, Runnable reactivateButtonRunnable) {
            launchWebService(reactivateButtonRunnable);
        }
    });

public void launchWebService(final Runnable reactivateButton){
    // 
    doRequest(new OnResponseListener(){
     @Override
     public void onSuccess(){
        // your custom code
        reactivateButton.run();  // makes button clickable again here
     }
     @Override
     public void onTimeout(){
        // your custom code
        reactivateButton.run();  // makes button clickable again here
     }
     @Override
     public void onFailure(){
        // your custom code
        reactivateButton.run();  // makes button clickable again here
     }
});
}

NOTE: this does not prevent Android from queuing click events on your button, but prevents your code from executing.

If you want to disable your button also, see Dalmas' answer and integrate that into this code where the clickable variable changes value....

DMonkey
  • 195
  • 2
  • 13
0

In short, disable the button on click, then reenable it with the callback from the service consumer function/method.

AlfredoVR
  • 4,069
  • 3
  • 25
  • 33