how does a good architecture for an android app look like? Should all the "work/business logic" been done in a background service and the Activity communicates just with the service to query/fetch data from somewhere (local/distant)?
Would you implement the "service" that the Activity calls as a real Android-service? Or a POJO-Singleton that does the work (perhaps using background threads). Or instantiate background threads in your activity for time-consuming actions (query a webservice).
How do you abstract your data access the right way? Would you use a ContentProvider to access/abstract your data? How/From where should it be queried? Activity? Service? ..?
I've tried to search for a good app architecture design, but I only found how the Android architecture looks like, not how an Android app should look like.
So what's your opinion about that? What components of an Android application should communicate which each other to ensure best extensibility/encapsulation,...?
There's no one answer to this question. Good OO design isn't Android specific. I'd say that the rule is - if the framework gives you a high level object (such as Service in the case of Android) that fits your use case, use it. If you find yourself making POJO implementations of the same things you get for free with the framework, go with the framework.
As far as separation of concerns, this is standard OO stuff. Don't put anything in your Activity classes that isn't the job of the Activity. Over-stuffing the Activity with methods and properties that the Activity needs but aren't really the job of the Activity is bad - makes the intention of your Activity hard to understand.
I usually separate stuff into sub-packages in my apps.
com.myname.myproject.app - base classes, global application functionality
com.myname.myproject.net - network stuff, network related utils
com.myname.myproject.data - db helpers, providers, etc
com.myname.myproject.model - object model
etc.
As far as communication within your app...
I always have a custom Application class that I register in the manifest. This way, when I have controllers and helpers that need to be a "single instance", I don't have to do all that crazy thread safe singleton stuff...I just keep one global copy of.
RoboGuice is a dependency injection framework that makes this even easier to accomplish...definitely worth looking into. If this interests you, the Google Group for RoboGuice is great and is constantly filled with the creators of the framework who can basically answer anything you need.
As far as in-app communication, I use my single instance Controller and State classes to hold state and do common tasks, and I usually use BroadcastIntents to communicate back to Activities from Services
Related
Where does Service (or BroadcastReceiver, etc..) belongs to in clean architecture package structure? I am wondering between domain and data layer... I would create new package called services in domain package. Is that right, or I should do it other way?
When thinking about clean architecture You should think of an Android Service in similar way as on any other Android application component like Activity for example.
Service and Activity can both do similar things like playing music, performing network requests etc. with one difference being the lack of user-interface in case of a Service (although one could think of a Notification as an UI for a Service). This lack of UI might be misleading at first.
Having in mind similar purposes of those application components we can imagine that both Service and Activity can be located in the same layer of the clean architecture project.
First I wouldn't choose the data layer as it is a place for Your data sources (concrete implementations of the abstractions defined in the domain layer) like web APIs or database controllers. One would argue that a Service is somewhat of a data source for the application because You can bind to it and get data from the background but if You look at Activities or Fragments You will notice that they can also be data sources for other Activities by using the Intents or arguments.
I wouldn't choose the domain package as well - it is supposed to contain definitions of the business logic of the app - interfaces of repositories etc. Moreover, this layer should be platform-independent, so no Android components should be there. A Service definitely does not belong there.
The app (or presentation) layer is left. It is an Android-specific layer - and this is the place for a Service. Service can communicate directly with a neighbour domain layer to access the data via use-cases that it can pass to a bound Activity, display a Notification with the data or whatever. All that while not violating the clean architecture rules.
I know that I can add a string or an integer by putting putextra() on my Intent but what do I do if I have to send a List?
For example, My main activity contains a list, I have a different activity that adds an item into the list and I have a third activity that needs to show the whole list
Your object can also implement Parcelable interface. Then you can use Bundle.putParcelable() method and pass your object between activities within intent.
Photostream application uses this approach and may be used as a reference http://code.google.com/p/apps-for-android/
Source: google "pass objects between activities android" :)
By making the Activity the central focus of the Android API, both in the API documentation and in most of their examples, Google has encouraged inexperienced developers to treat Activities as the sole constructs in an Android application. And, unfortunately, most of the widely available literature and over-simplified code examples available on the web perpetuate this.
However, good software design, regardless of platform or programming language, would suggest that you use the concept of a data 'model' - a class that contains the data that is important to your application, as well as methods that operate on that data. This class should be independent of any user-interface-related classes.
Activities are essentially a mash-up of Views and Controllers from the point of view of the popular Model-View-Controller (a.k.a. MVC) design pattern.
You should strive to remove the management of your data from the Activities, and put it elsewhere, in a non-Android class. Then make that class available to the Activities that need it, instead of simply passing data from Activity to Activity.
Where to put this model class? There are a number of ways to do it, including, but not limited to:
Make it a member of your Application class (subclass Application if you haven't already) - this is simple and convenient, but only reasonable for very small applications - it quickly gets out of hand
Make it stand-alone, but make all of the data members and methods static - again, simple and convenient, but only for a very small amount of data
Use a dependency injection library (e.g. Dagger), make it a Singleton, and inject into the Activities that need it.
The separation of app and service is just frustratingly disgusting.
The app and service do not have access to each other's variables and data can only be made available to each other through the Messenger. This results in duplication and makes the conversion of PC to Android code an absolute, absolute pain.
Is there an API or some trick to make them share data totally transparently, or do I just have to settle for this cumbersome rubbish implementation (which is the answer that I am expecting)?
You should read the Services developer guide, if you haven't already.
There are a variety of ways for Activity and Service to communicate with each other. If you bind the Service to the Activity, you can share data.
You can also create a custom Application object, which would let you share information across app components. A custom Application acts like a singleton.
Sorry. I'm new, so I'm experienced, but to follow the MVC design pattern in Android, where is the model stored? I was thinking in Application since it pretty much has a very wide scope and any component can pull from it. Is this a good way of thinking?
On a project that we have here, we do use the Application to persist it but in a certain structured pattern.
Just to start with, the Model is, as you would guess, layered through classes that will represent your persistent entities, so e.g. if you persist clients, you will have a Client class that will hold it's structure, so I guess when you say about Model, I think you talk about the persistence of state-full model objects that will live across your application lifecycle.
We use android annotations just to start with. We use singleton classes (Annotated with #EBean(scope=Scope.singleton)) and our Application object has a reference to that singleton.
We have other entities (singletons as well) that we use as controllers that are the only ones that are able to access and manipulate at certain degrees with that "model singleton" and our activities have an interface-like communication with the controllers, those controllers can access the persistent data on the "model singleton" and provide feedback to the activities through it's interface.
In general, it's probably better to use a ContentProvider or even a singleton class. The problem with keeping state in your Application is that if any part of your app ever needs to run in a different process, that process will have its own copy of the Application. Running things in separate processes isn't common, but there are a few reasons to do it. A singleton class doesn't address the problem of sharing state with another process, but the other process might not care about the application's model. If the model is in the Application, the other process gets a copy whether it wants it or not.
I am having trouble grasping the correct way to implement a centralized data access for different resources.
I want to have a single class, call it DataAccess.class that will call from both a SQLiteDatabaseHelper.class and a ServerAccess.class depending on what is appropriate when I call it's methods.
I thought extending DataAccess.class from a Service was the best approach so I can use ASyncTask for the ServerAccess.class. Now I am having doubts. The DataAccess.class needs to be accessible by most of the Activities in my Application, and I want it to stop when the Application does.
According to the google developer resources it sounds like a Service is well used for ongoing operations in the background but I am unsure how to handle the life cycle given the scope that I am trying to incorporate. Can I make the Service call startService() and stopService() internally when I use the DataAccess.class methods? Does it make sense to call it every time I access the Service or should this only happen once at the start and stop of the Application?
Thanks for the help,
I would recommend
1) Use all AsyncTask based solution because Service - Activity Communication is limited. (Unless of course you need to run something in the background) BUT I would love to hear the counterargument to this, why use a service instead.
2) Don't use just one Facade like DataAccess but make it specific to your app functions (ie sort of like System Services in Android).
3) You should use factories just like Android does to get the DataAcccess object you need. This addresses second part of where you get DataAccess object. Follow same model as getting and Android System service.
4) Use Content Providers where indicated and manage as indicated in Android docs.
Update: I think these are sort of the Axioms of a good solution. Not the whole thing. I will update as we consider this in depth.