“Write the code as if it would be accompanied by a violent psychopath who knows where you live.”Martin golding
When developing one of the projects using GooglePlacesAPI, I had a problem organizing network interaction between my Android – application and server API. Intuition and “noodles” from AsyncTask'ov suggested that there should be other ways of organizing this kind of interaction. So I came across the CommandProcessor design pattern. I want to tell you about the use of this design pattern in Android applications.
To begin with, I will describe the task that needed to be solved. It was required to write an application using the Google Places API, showing previews of any place on the map that the user chose, and then, if the user wants to get more information (for example, view more pictures), then upload pictures by the specified Id of the selected place, and show all the pictures already related to the selected location. The most obvious way for me at that time was to use AsyncTask. But after some attempts, it became clear that there must be other, more convenient ways. Using AsyncTask's was awkward because:
1) To get a preview of a place, you had to first make a request to get information about all the places that were near the place chosen by the user.
')
2) According to the received Id, form and send a request for receiving a photo preview.
3) When clicking on the preview, get all the pictures related to this place.
Thus, using AsyncTask, a kind of "waterfall" was obtained and one would have to use AsyncTask inside another. And then, googling, I found information about the Command Processor pattern, which does an excellent job with the tasks described above.
The CommandProcessor design pattern separates requests to the service from their execution. The main component of the pattern is the CommandProcessor, which manages requests, schedules their execution, and also provides an additional service, for example, storing requests for late execution or cancellation of a request. The diagram borrowed from [1] shows the relationship between the components of the pattern:

The scope of the pattern
- Programs in which the user interacts with the system through a graphical interface. For example: text editors, office applications. Commands (hereinafter, commands are the same as requests) are used to perform a task after the user has pressed the mouse button, hot key, menu button, etc. Commands are objects that are passed to the processor for execution.
- Distributed or Parallel systems. Using this pattern, you can send commands for execution in a separate thread. Create a queue of commands, etc.
- Applications that interact with the network.
Implementation
Now, we will consider how this pattern can be applied in the development of mobile applications, and specifically, Android – applications. There are a lot of ways to implement it; you can use the IntentService or HaMeR framework (Handler, Messages, Runnable). Let's look at how I implemented this pattern in a test application. So, the test application shows routes and a list of places that are contained in a particular route. Accordingly, we have two types of requests (commands): TracksRequest and PlacesRequest. Both classes are inheritors of the CommonRequest base class in order to be processed by our processor (CommandProcessor).
In the sendAsyncPlaceRequest method, all the work happens: it can be creating a URL for a request to an API, creating a new Thread, parsing a response and sending the result of the work to the controller using a Handler.
private void sendAsyncPlaceRequest(final int id){ Thread background = new Thread(new Runnable() { @Override public void run() { String response = sendRequest(getUrl(id)); List<Place> places = new ArrayList<>(); try { places = getPlacesFromJson(response); } catch (JSONException e) { Log.e("JSONException", e.getMessage()); } handler_.sendMessage(handler_.obtainMessage(States.PLACES_WERE_FOUND,places)); } }); background.start(); }
Next, you need to implement the CommandProcessor class, which will manage our requests and execute them:
publicclassRequestProcessor { private UpdateCallbackListener clientActivity_; public RequestProcessor(UpdateCallbackListener clienActivity) { this.clientActivity_ = clienActivity; }
Now we need a controller that, depending on the state, will send various commands to the processor. The result of the request is sent from the stream using Handler:
public class MessageController extends Handler { private static MessageController instance = null; private RequestProcessor processor_; public void init (UpdateCallbackListener listener) { processor_ = new RequestProcessor(listener); } public static MessageController getInstance(){ if (instance == null){ instance = new MessageController(); } return instance; } public void handleMessage(Message msg) { switch (msg.what) { case States.INIT_REQUEST: CommonRequest request = (CommonRequest)msg.obj; processor_.execute(request); break; case States.REQUEST_COMPLETED: List<Result> results = (List<Result>)msg.obj; processor_.updateActivity(results); break; default: break; } } }
In order to now return the result of the work to the activation, and call some updateUI () to update the user interface (ListView filling, drawing markers on the map, etc.) you need to define the UpdateCallbackListener interface:
public interface UpdateCallbackListener { void onUpdate(List<? extends Result> results); }
And implement it in our activism:
public void onUpdate(List<? extends Result> results){ tracks_ = (List<Track>) results; TrackAdapter trackAdapter = new TrackAdapter(this,tracks_); listView_.setAdapter(trackAdapter); }
After the result returns in response to the request (for example, a request to get all the places along this route), we need to update the assets and transfer the Place objects to the adapter. We can do this through the processor_.updateActivity (places) method, which will call onUpdate () in the activity that implemented this method. The following diagram, also taken from [1], shows the pattern dynamics:

To initiate a request, we need to create a TracksRequest object in the activation and transfer it to the controller:
controller_ = MessageController.getInstance(); controller_.init(this); TracksRequest tracksRequest = new TracksRequest(controller_); controller_.sendMessage(controller_.obtainMessage(States.INIT_REQUEST,tracksRequest));
Implementing with the IntentService
Using the IntentService also perfectly allows you to implement this pattern. Consider the chart:

As a command object, you can use an Intent and transfer it to our processor. Creator is our activity, which creates a command object and passes this object to the executor, that is, to the IntentService in our case. Thus, the role of the CommandProcessor is performed by the CustomIntentService class, namely the onHandleIntent () method which, depending on the data contained in the Intent, can perform various operations. To return the result to the activation, in this case you can use the BroadcastReceiver.
Step-by-step instruction
So, to summarize, to implement this pattern, you must do the following:
- Define the abstract command interface. The interface encapsulates the implementation of each individual command. In our case, it was the sendRequest method (int i) which each of the commands (requests) implemented differently.
- Determine the way the team returns the result to the one who called it. As shown for this, we defined the UpdateCallbackListener interface, with an onUpdate () method for each of the activations.
- Implement each of the teams. We had two kinds of requests - one for getting information about routes (TracksRequest), the second for getting information about places (PlacesRequest).
- Implement a controller that will send commands. Creating and sending commands can be implemented using Abstract Factory or Prototype. However, it is not necessary for the controller to be the creator of the commands. As you can see from the example, request objects were created in activti.
- Implement a class of processor that will accept the command and process. For each request, the RequestProcessor class executes the execute () method.
The advantages and disadvantages of the pattern.
Advantages:- In applications such as a text editor, different interface elements can use the same commands. For example, a button in the “Create” menu, and a button with the same name in the context menu can refer to the same command.
- Ability to send asynchronous requests, control the order of calls, depending on the result of the request.
- Flexibility when adding a new functionality in the form of a new command (request), without violating the existing functionality. Changing or adding a new command will not affect the command handler.
- Different clients (in our case, activites) can use the same commands. For example, a request to download an image by Id, can be used for different activations.
Disadvantages:- Additionally, you need to track each state and handle it appropriately.
- The number of teams can be very large
- Two-way communication. After the activation has initiated the creation of the request, and the response has been received, the result must be returned to the activation.
Conclusion
Most likely, you have already seen the implementation of the pattern in one form or another. But since the theme of the architecture of mobile applications is quite relevant, I hope the article was useful. In the future, we plan to consider several more patterns used in the development of mobile applications. Write questions in the comments, see you soon.
List of sources
[1] PATTERN-ORIENTED SOFTWARE ARCHITECTURE VOLUME 1. Douglas Schmidt, Michael Stal, Hans Rohnert, Frank Buschmann
[2] Command Revisited
www.dre.vanderbilt.edu/~schmidt/PDF/CommandRevisited.pdfTest project on github:
github.com/GregaryMaster/CommandProcessor