One of the most important things that you should focus on while developing a world-class app is the separation of concerns. It is good to separate and define clear roles for each component in your app. A class shouldn’t be a multi-tasking component. Many developers make a mistake of writing almost all their code in an
Fragment. Any code that doesn’t handle a UI or operating system interaction should not be in those classes.
Having a good design pattern saves you lots of problems. A good pattern ensures that all your code is organized and thoroughly covered by Unit tests. It makes debugging easier, since you know where to look for a particular problem. It also greatly improves the maintainability of your code.
There several architectural patterns, but the most popular being;
- MVC (Model View Controller)
- MVP(Model View Presenter)
- MVVM (Model View ViewModel)
I’m going to casually introduce each of the above architectural patterns.
i. MVC (Active Model)
MVC is commonly known as active model. The model notifies the view, when it is changed by the controller.
It also notifies other classes through the help of the Observer pattern. The Model contains a collection of observers that are interested in updates. The View implements the observer interface and registers as an observer to the Model.
Model: This is the data layer. It is responsible for managing the business logic and network or database API requests.
View: This is the UI layer. Its responsible for rendering the user interface. It is responsible for visualizing data from the data model.
Controller: This is the logic layer. It gets notified of the user’s behavior and updates the view accordingly. It is also in charge of updating the model as needed. For more information about MVC, this blog has you covered.
ii. MVP (Model View Presenter)
This is also known as the passive model. The presenter is the only class that manipulates the model. The model doesn’t not notify the view when it is changed by the presenter. Notification is done by the presenter. So the model is referred to as inactive or passive.
Model: This is similar to what we have defined above. It is the data layer responsible for managing the business logic and network or database API requests.
View: This is responsible for presenting data in a way decided by the presenter. The view is usually implemented by Activities or Fragments.
Presenter: The presenter acts as a link between the model and the view. All presentation logic must be defined here. It is responsible for querying the model and updating the view. It is also responsible for reacting to user interactions and updating the model accordingly.
This architectural pattern aims at ensuring that the view does as little work as possible. In other words, we have to keep the view as dumb as possible.
The presenter should also be framework-independent and shouldn’t depend on any Android classes. It should be a simple POJO class.
The backbone of this architectural pattern is an interface called a
contract that describes the communication between the view and the presenter. It cleans up the interactions between your view and presenter.
An example of MVP implementation;
Here are some sample code snippets from a simple stories App.
The contract file is an interface file that contains the
view interfaces. The
view interface provides methods that are responsible for drawing the user interface, whilst the
presenter interface contains methods that are responsible for the doing logic that is not dependent on the Android framework. It also contains methods that fetch data to be displayed on the user interface.
Below is how the contract file
StoriesFragmentContract is structured.
The presenter file implements the Presenter interface. The presenter interface defines the business logic of the application.
Finally, we have a Fragment (
StoriesFragment) which is responsible for displaying our stories. This fragment implements the view interface, which is responsible for drawing the android UI.
However, the above is a very simple and basic example of the MVP architectural pattern. you can refer to this blog post for further details about the same.
iii. MVVM (Model View ViewModel)
This is a very useful pattern that was introduced together with the Android Architecture Components.
With the help of the
ViewModel class, this pattern enables your app to survive configuration changes that come up as a result of device orientation changes.
This is because it combines the advantages of separation of concerns as provided by MVP while leveraging the advantages of data bindings. With this pattern, the model takes care of as many operations as possible while minimizing the logic in the view.
Unlike in MVP where the presenter holds a reference to the view, the
ViewModel doesn’t need to hold a reference to the view, because it exposes streams of events to which the Views can bind. The View however, has a reference to the ViewModel, but the
ViewModel has no information about the view, hence the principle; The consumer of the data should know about the producer, but the producer (
ViewModel) doesn’t know about who consumes the data.
The main players herein are;
Model: This is also referred to as the DataModel. Its main purpose is to abstract the data source. The
ViewModel works with the
DataModel to get and save data. This is the component in charge of business logic.
View: The job of this component is to inform the ViewModel about the user’s action. It is also responsible for drawing the UI. In the Android framework, this can be an
Fragment. This shouldn’t have any logic. Any underlying logic should be handled by the
ViewModel: This component is responsible for exposing streams of data relevant to the View. It retrieves data from the Model, applies the UI logic and then provides the relevant data for the view to consume.
The biggest plus on the above pattern is that it makes your app very easy to test. Unit tests can be easily written for the
ViewModel and Espresso tests for the
View are also easy to do. This is a broad pattern which can’t be wholly introduced here. More information about the same can be found here.
Ben Jakuben, in his post about Android Libraries clearly states that;
“A good developer knows to never reinvent the wheel, unless you plan on learning more about wheels!”
There are tons of open source libraries that developers can freely use in their apps. Some of these are so helpful that you shouldn’t start any App without them. One line of code in your app’s
build.gradle is sufficient to include any library of choice automatically.
Below, I’m going to casually introduce some must know libraries that make your Android development life fun and much easier.
This is my favorite library. It is the best library for making REST API calls. It makes HTTP Requests easy through annotations and automatically handles JSON parsing through the use of POJO classes. All you need to do is to define an API interface and a Retrofit class that automatically generates an implementation of your API interface. In your interface, you use annotations to describe the HTTP request.
A simple example of an API interface is;
The retrofit class that generates an implementation of the
GithubService interface shall look like this;
I won’t dive so deep into the intricacies of the Retrofit implementation. You can however go read about it from here;
In the Retrofit example above, I introduced
GSON while creating the
Retrofit object. I guess you wondered why!
GSON is a library that coverts Java Objects (POJOs) into their JSON representation. It can also be used to convert a JSON string to an equivalent Java Object. The library provides simple
fromJson() methods to convert Java objects to JSON and vice versa.
However, when using the
Retrofit library, you never have to make direct calls to GSON. The Retrofit class handles all that automatically when you add GSON as the
converterFactory. More information about the same can be found here.
Butterknife uses annotations to inject views by creating boilerplate code for you. It is small, simple and lightweight. It makes your code more readable on top of being easy to use.
Typically, you would call references to views in your Activity or fragment like so;
However, when we use Butterknife, our code becomes much more readable and concise. The same Activity code shall hence look like this;
For more information about ButterKnife refer to the Butterknife documentation here.
Dagger2 is a dependency injection framework, built on a simple concept called Inversion of Control. According to that concept, a class should not configure its dependencies statically, but should be configured from the outside. In Java, a class has a dependency on another class, if it uses an instance of that class. This is referred to as class dependency.
Since dependency injection in most world class Apps is a must know, Dagger2 is a true solution for problems that may arise during providing dependencies to particular classes. Ideally, classes should be as independent as possible from other classes.
Dagger2 uses code generation and is based on annotations. The generated code is very easy to read and debug. The annotations used are;
@Component among others.
For more information about dependency injection, Vogella has got you covered here.
If you have used Picasso before, trust me, Glide is a better option for fast and efficient image loading. Glide is a fast and efficient media management and image loading framework that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.
In simple terms, Glide takes up the burden of managing your media files especially if you are loading files from a network to itself. It automatically manages memory consumed by the image loading process and also automatically does caching for you, in a guise of reducing the pinch on network resources.
An image or drawable resource can easily be loaded into an image view by just calling;
GlideApp .with(CONTEXT) .load(URL) .into(IMAGE_VIEW);
Glide supports fetching, decoding, and displaying of video stills, images, and animated GIFs. For more information about the same, refer to Glide’s Comprehensive documentation here.
In order to build world-class apps, you need a clean ORM mapping library. Room was introduced during Google I/O 2017 as a persistence library aimed at cleaning up architecture in developing Android Apps.
Room in simple terms is one of the best SQLite object mapping libraries. It provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.
Persisting data offline greatly improves the experience of your users in cases where the internet connection is saggy. The goal of every app developer is to ensure that users have a seamless experience when using your App. Room hence bridges the gap by providing the easiest mechanism for data persistence.
You can find more information about Room here.
RxJava is one of the best libraries for enabling Reactive Programming in Android development. It is a framework for simplifying concurrency or asynchronous tasks. Multi-threading most times is a pain to developers and if not correctly implemented, it can cause some very difficult bugs to fix. RxJava comes in to make your life easier and help you avoid the nasty memory leaks.
Consider a case where you want to obtain data over the network and update the UI. One approach to achieve that is to use an inner
AsyncTask subclass in our Activity or Fragment.
The above seems like a safe approach, but it is not. It has some issues and limitations. Memory/context leaks are easily created by the above approach since
GetDataTask is an inner class and holds an implicit reference to the outer class. Notwithstanding, if you wanted to perform another long operation with the returned data, that may result in nesting another
AsyncTask which greatly reduces readability.
However, with RxJava, performing the same network call may look like this;
Network call with RxJava
The RxJava approach solves the problem of potential memory leaks that may be a result of running a thread holding a reference to the outer context, by keeping a reference to the returned
For more information about RxJava you can refer to this awesome piece.
In order to keep the article short enough, I’ll stop with the above libraries. But, you can read about; Ciceron, a nice navigation library, SlimAdapter a lightweight, slim, clean and typeable adapter without a need for a
ViewHolder, and Spruce Android Android Animation library among many.
Developing an App without Tests is like driving at 100mph without a seatbelt.
From the look of things, everything may seem fine and okay till you create a billion dollar bug.
In order to ensure quality Apps and a peace of mind when you launch your production ready apps, it is very important that you write sufficient unit tests for your business logic and espresso tests for UI tests. These tests save you from lots of unseen precedencies that may result in large uninstalls of your app due to unforeseen crashes. A thoroughly tested app gives you confidence that your app functions as expected.
Here is an espresso cheat sheet that shall save you tons of time when writing your UI tests.
Do’s & Don’ts
- Design for multiple screens
- Consider supporting multiple languages
- Provide your users with a seamless user experience
- Do performance tests
- Use user analytics tools
- Do Performance & Memory usage monitoring
- Develop for you device
- Reinventing the wheel
- Not using intents
- Not using fragments
- Blocking the main thread
- Not assuming success
Those are what I deemed as Billion $ tips for every Android developer. Hope you had a good read.
You can follow me on Twitter.