In this post we’ll be talking about architectural patterns used by Android application architecture.
Why understanding of patterns implemented by a certain architecture is important? Because it puts a new architecture we are learning into context of our previous experience and allows us to leverage our previous knowledge and skills.
Android documentation never mentions any pattern; at least I haven’t seen such references. But in reality Android does implement a number of patterns and architectural styles and I will show you this.
Android application architecture is a framework-based application architecture as opposite to a free-style application architecture.
What is the difference? A free-style application written in Java starts from a class with main() method and a developer is free to do pretty much whatever she/he wants.
As opposite to this a framework-based application is based on an existing framework and a developer extends certain classes or implements interfaces provided by the framework to build an application; the application can’t run outside of/without the framework it was built upon. Examples are Java web applications where a developer implements Servlet interface or extends one of its subclasses, or Eclipse RCP application where a developer extends one of Editor and View classes.
Framework-based architectures limit freedom of developers by prescribing what to do and how to do certain things. But in return they eliminate necessity to write a lot of “boilerplate” code and (hopefully) enforce well thought through design patterns.
There are many application frameworks available in Java. However Android team decided to build their own framework. Probably one of the reasons why they did it was necessity to support unique Android Java memory management.
In a “regular” Java an object is kept in memory until it is garbage collected. The garbage collection occurs only if an object does not have any reference to it from other “live” objects (see more details here). In Android it is not so. If a certain GUI gets hidden (it is not visible on the screen), there is no guarantee that it will be kept in memory even if the application intends to use it later. It might be kept in memory alright if Android OS has enough free memory, but it can be garbage collected as well at any moment when the OS finds that it needs more free memory. The same is true for processes as well. If an application process does not show any GUI to the user at the moment, it can be legitimately terminated by Android OS (there is one exception to this rule related to Android Services; we’ll discuss this later).
Here is an example. Let’s assume our application has GUI screen A and GUI screen B. A user accesses screen A first and then screen B; at this point screen A is not visible anymore. This means screen A and all logic that supports it may or may not be kept in memory. Since there is no guarantee that objects associated with screen A exist in memory while screen B is shown, the developer writing screen B logic must not expect that a certain object instantiated for screen A is still in memory. A side result of this is that Android architecture enforces “shared nothing” architectural style for Android applications. This means that different parts of Android application can invoke each other and communicate between them only in an explicit way; there is no shared state between them in-memory.
Well, what happens if the user decides to return back to screen A? She will probably expect to see the GUI in the same state as she left it, right? Here is how Android application framework solves the problem: it introduces so-called lifecycle methods in certain classes an application developer has to implement in order to create the application. Those methods are called by Android application framework at predefined transitional moments, e.g. when a GUI which was shown gets hidden or a GUI which was hidden gets to the forefront again etc. A developer can implement logic for storing and restoring state of objects inside those methods.
Such way of handling hidden GUIs and presence of “Back” button on Android devices makes it necessary to have a sort of GUI stack where the current visible GUI gets on top of the stack and all others are pushed down the stack (“push” stack operation). Pressing “Back” button removes the GUI which was on the top of the stack and shows the one which was below it in the stack (“pop” stack operation). Such stack exists in Android indeed. It is called sometimes “activity stack” and sometimes “back stack” in Android documentation.
Android application architecture follows very modern Model-View-ViewModel (MVVM) architectural pattern in how it handles relationships between GUI and a logic supporting the GUI. This is actually good news for Android developers since this is the latest and greatest architecture for GUI applications at the moment.
MVVM architecture was created in attempt to solve a disparity of skills which occurs when e.g. a Java developer tries to build GUI in Swing or a Visual C++ developer tries to build GUI in MFC. Developers are smart folks and have many skills, but building nice and sexy GUIs requires quite different talents than those the developers usually have. It is work more suitable for GUI designers. Good GUI designers are more artists and a user experience professionals than experts in designing and writing code, so we can’t expect from them writing a good code. Clearly, it would be better if a GUI designer was designing a GUI and a developer was writing a code which implements a logic behind the GUI, but such technologies as Swing or MFC simply do not allow this.
MVVM architecture overcomes this contradiction by clearly separating responsibilities:
- GUI development is done by a GUI designer in technology more or less natural for this task (XML)
- Logic behind the GUI is implemented by a developer as ViewModel (which actually means Model of View) component
- Functional relationships between GUI and ViewModel are implemented through bindings that essentially define rules like “if a button A is clicked, method onButtonAClick() should be called on ViewModel”. Bindings can be written in the code or defined in a declarative way (Android uses both types of bindings)
MVVM architecture is used in one way or another by all modern GUI technologies like Microsoft WPF and Silverlight, Oracle (former Sun) JavaFX, Adobe Flex, AJAX.
We mentioned that different parts of Android application can invoke each other and communicate between them only in an explicit way. How this is done? Android application framework uses several communication patterns:
- Message passing which involves Intent class
- Publish/subscribe or pub/sub which also involves Intent class and BroadcastReceiver class
- Late binding and method calls that are used for accessing ContentProviders and local (in-process) Services
- Late binding and Inter-process Procedure Communication (IPC) for invoking remote (AIDL) Services
Don’t worry if some of the above sounds confusing. We’ll discuss all this in greater details in later posts.
That’s all for now.