Category

Android

Android Architecture Components Part 2 – Dependency Injection

As promised, part two is here. ūüėɬ†Before we get our hands dirty,¬†let’s do a quick recap. In the¬†previous post, we created a simple app that displays a list of user names using¬†Android architecture components¬†library. We divided our app into the following layers for better code responsibility and separation of concerns:

  1. View/UI layer
  2. ViewModel layer

This worked pretty well but our data was hard coded. In this series, we will setup Retrofit for API Calls & Dagger 2 to add Dependency Injection to our app and use TMDB API to get some data. With that said, our new architecture will look like below.

Picture from: Android developers site

Before We Begin …

Who the hell is Dagger and what is Dependency Injection? Worry not we will walk through this first. So let’s define some terms.

Dependency: This is when a  class has a dependency on another class, if it uses an instance of this class. We call this a _class dependency.

Dependency Injection: Also known as DI. Dependency Injection is a technique whereby one object supplies the dependencies of another object. This means an object creating its dependendencies via new operator is strictly prohibited.

We will be using Dagger 2 for DI.

Dagger Annotations

Dagger 2 uses the following annotations:

  • @Moduleand¬†@Provides: define classes and methods which provide dependencies.
  • @Inject: request dependencies. Can be used on a constructor, a field, or a method.
  • @Component: enable selected modules and used for performing dependency injection
  • @Singleton : annotation ensures the class instance as singleton across the dependency graph.

Dependency Injection can be a beast and I don’t want to dive into it. There are a couple of articles that talk about this. I’ll add them at the end of the article. ūüėÉ

Project Structure

For some organization, We’ll handle injection in a package called di.

Let’s Code

The source code is available on Github.

You’ll need to add dagger dependencies to your build.gradle¬†file

Creating Modules

We’ll set up a couple of module classes.

  1. App Module: This will ensure that TmdbService will be a singleton throughout our app.
  2. NetworkModule: This helps us setup retrofit and logging.
  3. ViewModelModule: Module to set up our viewmodels.

Let’s set up our modules:

NetworkModule.

We’ve done a couple of things in the¬†NetworkModule that I think are work taking note of

  • provideOkHttpInterceptors(): Sets up HTTP logging. This will allow us to monitor network requests and responses. It will only log when running the Debug version.
  • okHttpClient(): Sets up OkHttp client with some custom configs.e.g Adding HTTP logger, set timeout & read duration and custom interceptor that adds TMDB API key to requests.
  • provideRetrofitClient() : Sets up Retrofit client.

AppModule

Now that we have the Network module created, we can create an app module that will now ensure we have a singleton for our API¬†service interface. If you’ve not used Retrofit, the interface defines API endpoints. It simply looks like this.

Here’s how the NetworkModule looks like. We’ve added the NetworkModule and ViewModelModule to the AppModule.

Note:
The method names for the providers, such as provideTmdbService(), provideRetrofitClient(), are not important and can be named anything you like. Dagger only looks at the return type.

Create Components

We only have one component at the moment AppComponent.

We’ve specified the modules we want to be used with the component inside the @Component annotation.

Boom. We are done setting up our dagger. ūüėÉ

Let The @Injection Begin

Now that we have all our dependencies set up, let’s use them.

1. Application Class

We need to initialize the dependency graph for our application by using the Component. This is pretty simple in Dagger 2.

AppInjector.init(this);

Don’t forget to add property android:name=".TmdbApp" to the tag in AndroidManifest.xml file.

2. TmdbRepository Class

I’ve created a class TmdbRepository in the repository package that is responsible for making API requests and returning data to our ViewModels.

We’ve used @Inject annotation on TmdbRepository constructor which in turn tells Dagger that to use the constructor to create an instance of¬†TmdbService.¬†This adds this class to the Dependency Graph.

3. MainActivityViewModel Class

As discussed earlier, using @Inject annotation on MainActivityViewModel constructor which in turn tells Dagger that to use the constructor to create an instance of TmdbRepository.

By doing so, the ViewModel does not care how we get out data. It just wants data from our repository.

4. ProjectViewModelFactory Class

ProjectViewModelFactory implements ViewModelProvider.Factory. This class is responsible for instantiating our ViewModel classes.

5. MainActivity Class

We can now use load data in our MainActivity. We call getPopularMovies() which will return some data. We then use observe which will listen for any changes to our data.

This is how the entire code looks like.

Wrapping it up

You can download the final project on Github

Dagger can be a bit of a pain when starting but don’t let it get to you. Dependency injection becomes useful when implementing proper testing into your app, allowing mock implementations of back-end APIs and data repositories to be used in testing.

There’s much more to learn about in Dagger 2 and its usage, including:

  • Scopes
  • Subcomponents
  • Testing with Mockito

In the next series, well look at setting up the UI and maybe writing some tests. In the meantime, happy injecting.

References

  1. Vogella РDependency  Injection
  2. YouTube video by Gregory Kick: DAGGER 2 РA New Type of dependency injection
  3. YouTube video on DI by Dan Lew: Dependency Injection made simple
  4. Dagger 2: official page
  5. Codepath: tutorial on Dagger 2

 

 

Android LiveData & ViewModel

If you missed it, there were some awesome announcements about Android at Google I/O 2017. Say hello to Android Architecture Components.

Architecture Components.

A new collection of libraries that help you design robust, testable, and maintainable apps. Two main pain points addressed by Architecture Components are:

  1. Help manage UI components lifecycle.
  2. Persistent data during configuration changes.

We’ll briefly¬†take a look at the main components then jump into some code.

There are 3 main components:

  1. Room
  2. ViewModel
  3. LiveData

LiveData: allows you to observe changes to data across multiple components of your app without creating explicit, rigid dependency paths between them. LiveData respects the complex life cycles of your app components, including activities, fragments, services, or any LifecycleOwner defined in your app.

ViewModel: Provides a way to create and retrieve objects that are bound to a specific lifecycle. A¬†ViewModeltypically stores the state of a view’s data and communicates with other components, such as data repositories or the domain layer which handles business logic. To read an introductory guide to this topic, see¬†ViewModel. It¬†exposes the required data and interested parties can listen to it.

Room: is a persistence library that makes it easier to work with SQLiteDatabase objects in your app, decreasing the amount of boilerplate code and verifying SQL queries at compile time.

Project Overview

To demonstrate all we’ve just gone through, we’ll build an app in various stages, by the end of this blog-post series, we’ll have built an app that fetches data from Github Api.¬†We’ll use MVVM architecture in this tutorial. ¬†As mentioned earlier,¬†ViewModel¬†exposes the required data and interested parties can listen to it.¬†

Getting Started

The source code for this project can be found on GitHub.

I am using Android Studio 3.0 Preview for this project. If you don’t have it, go ahead and download it. You can run it alongside with other versions¬†so don’t panic. ūüôā

Add the following architecture dependencies to your app level build.gradle file.

Now that we have that setup, let’s create the ViewModel class. For now, we will hard code some data, just to get us started. We’ll use a handler to simulate a delay which ideally happens when loading data from a server.

Let’s look at the code before we move on.

ViewModel Code Breakdown

  • Every ViewModel class must extend the¬†ViewModel¬†class. If your ViewModel needs the application context, it must extend¬†AndroidViewModel.¬†The ViewModel will contain all the data needed for our¬†Activity.
  • Our¬†LiveDatanow completely encapsulates the loading process, loading the data only once. This is handled by¬†getGitUserNames().
  • setvalue()¬†cannot be done in background thread it must be done in main thread only.

Final Step: Connecting UI to ViewModel

Now that we have the ViewModel class, we can use it in our activity by creating an instance of it. This will allow us to have access to getGitUserNames().

MainActivity Code Breakdown

  • We have to useLifecycleActivity because¬†it provides us with the state of the lifecycle.
  • If you see functions with Arrows, don’t panic. The are Lambda Expressions. You can check out a previous article on this.

That’s it. We are done. Pretty simple. Right??

 

Take note of when the orientation of the device changes. Data does not get reloaded again.ūüėɬ†Because we used ViewModel along with LiveData class to store data during orientation change, new instance of activity will be created but the data won’t be downloaded again. ViewModel will provide the most recent available data.

 

What Next

This is not over. In the next articles, we’ll cover:

  1. Dependency Injection.
  2. Fetching data using Retrofit.
  3. Room.
  4. Unit Testing.
  5. ….

 

Stay tuned for more posts.

The source code for this project can be found on GitHub.