views:

86

answers:

2

I don't know how to elegantly solve the following task:

  1. I have several blocks of code (operation) to execute.
  2. Each block can return true of false to indicate that further execution is possible.
  3. Inside of each block I have to use asyncronous methods calls (Because Android is completeley asynchronous).

Example of processing operations (not working now as expected):

      List<Operation> operations = command.getOperations();
      for (Operation operation : operations) {
          Log.d(TAG, "Processing operation: " + operation);
          OperationResult result = operation.execute(activity);
          Log.d(TAG, "Operation result is: " + result);
          if (!result.canContinue()) {
              break;
          }
      }

The problem is that inside of the operation I need, for example, display AlertDialog and wait for the input. But after I call dialog.show() my method execute finishes and it returns incorrect result.

Example of the button listener, registerd with AlertDialog is below:

 final OperationResult result = new OperationResult();
 final class ButtonListener implements DialogInterface.OnClickListener {

    public void onClick(DialogInterface dialog, int id) {
        switch (id) {
        case DialogInterface.BUTTON_POSITIVE: {
                result.setCanContinue(true);
        }
        case DialogInterface.BUTTON_NEGATIVE: {
            dialog.cancel();
                result.setCanContinue(false);
        }
    }
}

How should I modify processing of operations to support asynchronous model of Android?

+2  A: 

If the amount of processing to be done is in the milliseconds range, you could restructure your code as a state machine - a list of enumerated subtasks and a variable that keeps track of the current or next task to be executed. Essentially, when an event comes in you will work through the to-do list until you get to a task (a state) that requires the result of an asynchronous operation. At that point you launch the asynchronous operation and return. When you get an event call from user input or whatever, you record the data and then resume executing the state machine from the saved state number until it again hits an asynchronous operation and you return. But this only works if the time you spend processing is measured in milliseconds, otherwise you act laggy and unresponsive, triggering ANR in extreme cases.

If you need to do more processing, you should do it in a background thread or a service, which posts messages to the UI thread to launch asynchronous events and then waits for the UI thread to be called with an event that can be translated into the needed result, but meanwhile leaves the UI thread free to respond to unrelated events.

Chris Stratton
Amount of processing can be big, actually. Now I'm restructuring my code so it will be event-driven.
uthark
A: 

Ok, here is how I solved the problem:

  1. I've Created context of execution, which is shared between operations.
  2. Each operation can invoke next operation, stop further processing, etc. using appropriate methods.
  3. Each operation can be either background service, either Activity.
  4. After completion of all operations caller is notified via callback.
  5. Since operations also can be asynchronous, they using notifications to know when operation is completed and further processing should be done.
uthark