Having many options leads to frustration. This is the summary that I can make about the refactoring process that I’m stuck into. Following a redesign phase in which I’ve rethought everything, but ultimately does not imply deep changes, I find myself engrossed in the new implementation in which the service is the center of everything, and both the activity and the widget, feed from their knowledge.
Unfortunatelly, that implies communication, and which a priori seemed a simple task is complicated by a very different life cycles, and above all by the multitude of possibilities for this communication.
There is an “Android way” of doing this, that involves defining some interfaces (through AIDL) to communicate the service and any other components, bind them, and let them communicate through these interfaces. This method is very powerful because it allows the service to communicate even with other applications or other processes. But this way implies unnecessary complexity for OTempo, because it only needs to communicate the view with the service within the same process.
At the other extreme we have the possibility of building a kind of Singleton in the service, initialized only when android decides to create it. The view simply access the Singleton and get the information needed. The main problem with this alternative (which I confess, was the first I tried) is that we have no guarantee about when the Singleton will be initialized. And to further complicate the problem, since the view and the service are created in the same thread, but asynchronously, it is very difficult to get the view to have a valid reference to the Singleton. Several of my attempts ending in a funny deadlock. Sure there are dirty hacks that can solve this problem, but as the whole thing is a hack seen from an Android purity prism, I decided to take some other route.
For now I have decided to follow a middle path. I’m going to bind views with the service, because it is a very safe way to avoid problems with the lifecycles. However, since everything will happen within the same process, I will omit AIDL interfaces, and will use the bind approach only as a way to ensure getting the references I need.
My last question is how to limit the service lifecycle. I have two choices: I can have the service active only when the user has the application open or the widget visible (to save battery life), or I can always have the service active (to be always up to date). Since I do not get to decide for one of them, I am proposing to allow the user to configure it.