views:

257

answers:

3

I'm trying to prevent my application to call the same method twice in the event of a double-click, or if the user presses different buttons quickly, almost at the same time.

I have clickable Views, acting as buttons, that call the same method but passing different parameters. This is the call:

startTheSearch(context, getState(), what, where);

Inside this method I'm creating a new Thread, because it queries a web server for the result:

new Thread(new Runnable() {

 public void run() {

    progDiag = ProgressDialog.show(ctx, null, "Searching", true);
    getServerXML(context, what, where, searchIsCustom, mOffset);
       handler.sendEmptyMessage(0);
 }
 }).start();

The problem is that upon two quick clicks, the method is fired twice, two threads are created, and consequently two new activities are created. That makes my app crash.

When the methods are done, and we have the result from the server, we call the handler:

private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
try {
Intent i = new Intent(Golf.this, Result.class);

Bundle b = new Bundle();
b.putString("what", mWhat);
b.putString("where", mWhere);
b.putInt("offset", mOffset);
b.putBoolean("searchIsCustom", searchIsCustom);
i.putExtras(b);

startActivityForResult(i, Activity.RESULT_OK);
progDiag.dismiss();


} catch (Exception e) {
 Alerts.generalDialogAlert("Error", "settings", ctx);
}

}
};

I tried to have a global boolean variable called "blocked" initially set to false, creating a condition like:

if(!blocked){
 blocked = true;

 new Thread(new Runnable() {
  public void run() {

But this only seems to work on slower phones like the G1, I tried on Nexus and before it set blocked = true, the second request has was granted. So is there any way I can block the method being called if it's already running, or if the thread has started so it wont create a new one?

Please, I really need to fix this. I've been developing on Android for almost 2 months now, but I'm yet to tackle that bug. Thanks in advance.

+1  A: 

I tried on Nexus and before it set blocked = true, the second request has was granted

That is impossible. Android UIs are single-threaded. There is no way that two onClick() methods of OnClickListeners will be called at the same time.

CommonsWare
+1  A: 

In the book Hello Android the author Ed Burnette gives a very nice solution for this problem. To leave your app snappy and responsive you should create a second thread to do the web request.

Instead of creating a new thread for every request you can use a SingleThreadExecutor. If you start a second thread you can check if you are waiting for the result of another thread and block until this thread is ready, or cancel the old thread and start a new one if you think that the user now wants to do some other thing.

You can find the source code from the book on this page. Look for the Translate folder inside the source. It is a nice example on how to react to user commands and how to prevent too many web requests because of a user touching a lot on the gui.

Janusz
A: 

Instead of using the "blocked" Boolean, you might investigate using a mutex. They're designed for this kind of problem.

TreDubZedd