OK, we looked at Android application architecture background and architectural patterns implemented by Android application architecture. Now let’s talk about main parts of an Android application.
In this post we’ll introduce main “personages” of Android application architecture.
Android application usually consists of:
The diagram below represents a class hierarchy of main classes from Android SDK a developer has to deal with while developing Android application:
There are much more classes than that, but those are the main ones. Classes highlighted in yellow are those a developer has to deal with (e.g. extend) directly. Other classes are important as well, but they are relatively rarely used directly.
View class is a base class for all GUI widgets. Android application GUI is a tree of instances of its subclasses i.e. GUI widgets. One can build the tree programmatically, but this is not how you should do this. GUI is normally defined by an XML GUI definition (layout file) and inflated (Android term) automatically into a tree of corresponding objects at runtime.
Activity class and its subclasses are the ones that provide logic behind the GUI. Actually it corresponds to ViewModel in Model-View-ViewModel architecture pattern (MVVM). Relationship between subclasses of Activity and GUI layout is 1-to-1; normally each subclass of Activity has one GUI layout associated with it and vice-versa. Activity has a lifecycle.
During the lifecycle Activity can be in one of three states:
- Active and running when its GUI is in the foreground (technically speaking – on top of activity stack)
- Paused if its GUI lost focus but it is still visible. No code is executed in this state
- Stopped if its GUI is not visible. No code is executed in this state
Activity code runs only when the Activity GUI is visible and has focus. Also there is no guarantee that Activity object and its associated objects are in memory while the Activity is paused or stopped (very important point to remember; we discussed this Android memory management peculiar feature earlier).
ContentProvider class and its subclasses correspond to Model in MVVM architecture. In most practical cases it is a wrapper around SQLite database with rather fancy URI-based way to query the database. Theoretically nobody prevents a developer from building ContentProvider which will be using something else instead of DB for storing data. However given that query() method of ContentProvider returns Cursor object which is quite similar to JDBC ResultSet interface and the way how the query is made, nobody would doubt that the real purpose of ContentProviders is to encapsulate a database.
I don’t know how Android team came to such design, but my guess is here we have a combination of two good but not very compatible ideas.
Here is why I think so. The whole idea of content provider is likely inspired by AJAX application architecture. AJAX applications normally use MVVM architecture where Model is represented by particular URIs on a server side (however this has changed somewhat since introduction of HTML5 which allows storing data locally). Indeed, the fact that ContentProvider class is queried by URIs and makes extensive use of MIME types points to AJAX as an origin of the design. Remember, Google folks were developing a lot of AJAX software, e.g. Gmail, Google Docs etc, so it was natural to borrow ideas from AJAX application architecture for them.
Probably somebody else came with another cool idea: how great it would be to have a fully functional relational database running on a mobile device! (note, this was happening at around 2005 when mobile phones were much less powerful than now). And as a result they combined two good ideas into one ContentProvider class. As it often happens in software development combining two great ideas not always results in a good design; in Android case we have rather confusing ContentProvider design.
Service class and its subclasses are something which I have difficulty to classify. I think, Google folks have the same difficulty (please read their javadocs). They classify it by mostly describing what it is not. I would personally classify it as a special type of Model, serving a bit different use case than ContentProvider does.
In my opinion, architecturally design of Android Service was inspired by OSGI services.
I think Service is the solution Google folks came up with to solve a logical problem they created in Android application architecture with its threading model.
Think of this: Activity is active and running only when its GUI is on foreground. As soon as another Activity GUI comes in front of the current one, the current one stops running even if it was doing something. And what if you need to perform certain operation even when the process which tries to perform it is not on foreground? You can’t do this with Activity. You can’t do this with ContentProvider as well since it does not have its own lifecycle and it can run only while Activity which uses it is active.
Here Service comes to the rescue. It can be executed even when the process it runs within is not on a foreground. So if you develop Activity which must perform a long running operation which should be completed even while running in background, you should create Service implementing that operation and invoke it from Activity.
Service has a lifecycle as well. This means that it can be instantiated and run by Android application framework under certain conditions (we’ll discuss this later).
As I mentioned, as a Model, Service is somewhat of more general purpose than ContentProvider. It can use DB, but its API is not bound to DB as ContentProvider API does. In many cases Services are used to connect to external servers.
BroadcastReceiver class and its subclasses serve as “subscribers” in publish/subscribe (or pub/sub) communication mechanism implemented by Android application architecture.
Intent class and its subclasses serve as messages in message passing and publish/subscribe communication mechanisms implemented by Android application architecture.
We’ll discuss the communication mechanisms in another post later on.
Of course, Android application developer is not limited to just extending Android SDK classes. She can write her own classes as she wants. But all they will be just “helper classes” of sorts for those main classes derived from Android SDK classes.
Android manifest is another important part of Android application. The idea has been clearly inspired by Eclipse plug-in manifest.
Android manifest is an XML file and it serves several functions. Here is Google description of manifest functions:
- It names the Java package for the application. The package name serves as a unique identifier for the application.
- It describes the components of the application — the activities, services, broadcast receivers, and content providers that the application is composed of. It names the classes that implement each of the components and publishes their capabilities (for example, which Intent messages they can handle). These declarations let the Android system know what the components are and under what conditions they can be launched.
- It determines which processes will host application components.
- It declares which permissions the application must have in order to access protected parts of the API and interact with other applications.
- It also declares the permissions that others are required to have in order to interact with the application’s components.
- It lists the Instrumentation classes that provide profiling and other information as the application is running. These declarations are present in the manifest only while the application is being developed and tested; they’re removed before the application is published.
- It declares the minimum level of the Android API that the application requires.
- It lists the libraries that the application must be linked against.
Please note the second point. It means even if there is a class extending Activity, ContentProvider , BroadcastReceiver or Service within an application, the class can’t be used unless it is explicitly described in Android manifest.
Any modern GUI application technology uses resources in some form. Android applications are not an exception of the rule. They use following types of resources:
- GUI layouts (XML files)
- Menu definitions (XML files)
- Textual strings
The way resources are referenced by Android applications is somewhat unusual. Normally in Java resources are identified by strings. Such strings may contain e.g. a path and a name of a file containing the picture or an ID of particular string etc. The problem with such approach is that mistakes in those references could not be caught during code translation.
Let’s consider following example. A file named mybutton.png contains a picture for a button. A developer makes a mistake and types mybuton.png as a reference to the resource in the code instead of using the correct file name. As a result the code is instructed to use nonexistent resource, but the code will compile just fine. The mistake may be discovered only during testing (and may not be discovered at all).
Google folks came with an elegant solution to the problem. Android application build generates a special Java class named R (just a single letter name) for each package where classes use resources. This class has a number of static final data members. Each such data member is a reference to a particular resource and they are used in Android Java code for referencing resources. Due to this each mistake in referencing resources is discovered at compile time.
Android applications use several different types of files:
- “General purpose” files
- Database files
- Opaque Binary Blob (OBB) files (those represent encrypted file systems on its own that can be mounted for the application)
- Cached files
Although ultimately they are all just Linux files, it makes sense to consider them as separate types of files since they are handled by different Android APIs and stored separately. There is also a distinction between files stored in internal device storage and in external device storage (the latter may be not present or disappear/appear at any moment).
APIs for working with the files are implemented by Context class which is an ancestor for Activity and Service classes. We already discussed this class here.
That’s all for now. In the next post we’ll discuss how different parts of Android applications communicate between them.
Read Full Post »