After adding a lot of features and conditionals to the OTempo service, and after almost going mad to keep a legible and safe code, I decided to use the state pattern.
The fact is that OTempo needs to handle a lot of cases when updating station predictions:
- The activity may be starting and needing just one station, but with really high priority.
- The widget may be updating and needing its own station, not so fast.
- The service may be updating all the stations to have them cached.
- Internet may be enabled, or disabled.
- The user may have background app updates enabled, or disabled
- An update cycle may have ended, or not. And meanwhile the user may terminate the service.
- Internet may return from an off state.
- Make a list of all the situations in which your service has a very different behaviour.
- Now make a list of all the events that may provoke a change from one situation to another.
- Now, for each state, think what should happen if any of these events are fired. Some events will transition to another state, some other should not change state.
- Write this diagram into paper and paste it in a visible place.
- Create a State interface, with one method for each possible event. These methods should receive the context (the service) and any other data that describing the event itself.
- Add a State attribute to the service (current state)
- Create a concrete State class for each of the mentioned situations.
- Implement the interface methods on these classes. If some event should trigger a state change, then ask the service to transition.
- Add logging code to the service method that handles transitions, to be able to debug.
- Reimplement the service loop as a call to the current state (ie, update())
- Delegate any event that you detect in the service to the current state.