How to have a method pause and wait for input with Android?

Ivan S picture Ivan S · Oct 26, 2010 · Viewed 9.5k times · Source

Basically I have created a Blackjack app that uses several methods that get called and pass a long the information that is needed (about cards and actions). I have 2 buttons displayed on screen that are click able (hit and stand). Now I have a method called player turn... and this is when I (through static ints) have if a button is selected, things will happen. However I did this with an infinite while loop thinking it will just keep checking to see if a button is pressed and then only do action when a button is pressed. This isn't working as my screen is not refreshing after each textview or imageview change thus as soon as I hit start game the game appears to "freeze" (being due to the method never ending) and I am therefore unable to click said buttons. Is there a way to call something similar to keyboard listener in java (Which pauses activity and waits for user input), in android? If not, what would you suggest the workaround be? Lastly (though not as currently important) how would I properly refresh everything after each change (I believe I need to use invalidate.. though I'm not sure what to have before invalidate so it refreshes the whole thing)? Thanks a bunch in advance.

Answer

rekaszeru picture rekaszeru · Apr 12, 2011

Looks like a new Activity (invoked by startActivityForResult), and a Handler (called from the onActivityResult) could solve your problem.

Take a look at the design-snippet bellow:

activity interactions

Let's say the method you are willing to 'sleep' is the doSomething from the MainActivity class. I assume this is invoked from some event handler implementation. You should move all the calls from that method into the BackgroundActivity activity, - which should show a ProgressDialog and/or nothing else -.
In your doSomething method you should start an activity by an intent pointing to the BackgroundActivity with

this.startActivityForResult(new Intent(this, BackgroundActivity.class), 
    BG_ACTIVITY_ID);

where BG_ACTIVITY_ID is your unique identifier for the started activity, so when it finishes, you can handle it.

Inside the processBackgroundData (or when the background activity is finished processing), you should set the result before calling finish():

final Intent intent = new Intent();
intent.putExtra(KEY_FOR_DATA_YOU_NEED, dataYouNeed);
setResult(Activity.RESULT_OK, intent);
finish();

In your MainActivity you should also override the onActivityResult method, to retrieve the necessary information from the finished BackgroundActivity task:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    //you might also want to check if the resultCode is `Activity.RESULT_OK`...
    switch (requestCode)
    {
        case BG_ACTIVITY_ID:
            //get the data you need 
            final String dataYouNeed = data.getStringExtra(KEY_FOR_DATA_YOU_NEED);
            //process the data...
            //if necessary (threads!), call your backgroundHandler's 
            //sendMessage with the retrieved informations as obj.parameters
        [...]
            break;
        default:
            [...]
            break;
    }
}

And inside your BackgroundHandler's handleMessage method (since you are back to the ui thread: the thread in which your main application is running) you can do all the necessary ui modifications, and also listen forward for the user events.

This way you are getting rid of the infinite loop, and can always be aware of user interactions.