Transcripts
1. Welcome: Welcome to the course dependency injection on Android
using Health. My name is Garrett or hue. I'm developing Android
applications since 2013. In this course, you are going
to learn what's dependency, why it can be problem, and how to solve that problem
using dependency injection. You will learn how to implement dependency injection using
library called hilt. Also, we are going to create simple weather forecast
application using hilt. In order to take this course, you should be familiar
with Android development. We are going to use Kotlin
programming language. Also. You should have Android Studio installed
on your machine. If you're ready, let's
start the course.
2. Example: Let's start the course
with quick example of dependency and
dependency injection. Here I will show
example of dependency. This is the engine class. It has start function which
brings engine is starting. And we have Car class, which creates
instance of engine. And it has start function which prints car is starting
and it starts engine. Also we have main
function where we create instance of car and we started. The problem is here, this line, we're creating instances
of engine inside car. In this case, engine
is dependency. Car is dependent
on engine glass. How we can solve this problem? It can be solved. Moving, creating instance
outside of dependent, we move it to main function and we pass an instance to the car. Now we are parsing instance engine into car
using its constructor. This is called
dependency injection. Let's run this code
and see the result. Code is working. And this was quick
example of what's dependency and
dependency injection.
3. Dependency: In this video, we will
see what dependency is. Dependency happens
when one component depends on another component. E.g. one class depends
on another class. This example, we are creating instances of engine inside car. So car depends on engine. In this case, car is dependent,
antigen is dependency. You can say what can be
problems with Dependency. First problem is
called replication. We are creating instance
engine inside car. So we may need to create such
instances in many places. This results in
code replication. Another problem is
maintainability. Imagine the situation when engines constructor
function chains. So we need to change
the code everywhere where we are creating
instances of engine. Another problem is
Lifecycle Management. Here we are creating instances
of engine inside car. This means that when
car is removed, engine is also removed. These problems can be solved by using
dependency injection.
4. Dependency Injection: In this video, we will see
what dependency injection is. Dependency injection is creating and
injecting dependency. This example, we are creating
an instance of engine in main function and passing in two cars constructor function. And this is called
dependency injection. Dependency injection solves
problems with dependency. It's source code replication by creating dependency
in one place. In this example, we are
creating instances of engine in main function and
passing into car object. If we need to change and
its constructor function, we need to change
code in one place. So this improves code
maintainability. Dependency injection solves problem with
Lifecycle Management. Here we are creating
instances of engine and passing car object. So when car is removed
and is not removed, so we have control
over life cycle. There are three types of
dependency injection, constructor, field
and method injection. As we have seen in
previous example, dependency is created and pass it into the
constructor function. This is called
constructor injection. This type is preferred
as we can make dependency private to
make it immutable. Another type is
filled injection. In this case, we inject
dependency into field. This type of injection is used when constructor
is not available. Example is Android system. We don't have control
over Android components like activity, fragment and etc. Another type is
method injection. This type of injection is used when we don't have
control over constructor. And we want to inject multiple
dependencies at once.
5. Service Locator: In this video, we will talk
about service locator. There are two ways of
solving dependency problem. First way is
dependency injection, where dependencies are
injected into dependent. In order to implement
dependency injection, we can use healed library. Another way to solve dependency problem is
dependency lookup, where dependencies are
retrieved from outside. So called service locator, which returns dependencies
by their name. Let me show an example
for service locator. Here we have glass engine with function star which prints
engine is starting. Here we have object
called service locator, which creates instance
of engine and function, which returns dependencies
by their name. E.g. it returns instance of engine when name
equals two engine. If name is not found, it throws an illegal
argument exception with message dependency with the following key has
not been found in car class. Instance of engine
is retrieved from service locator using lookup
function with engine key. Then start function prints car is starting and
starts the engine. In main function, we
create instance of engine and call it
start function. Service locator is
designed pattern which gives access to
the object by its name. It allows to create objects in one place and get
them by their names. It solves dependency problem by creating instance
in one place. So there is no code application. It also creates
dependency outside. So change in dependency does not result in
change in dependent. Moreover, lifecycle
of dependency is not bound to life-cycle
of dependent. Service locator is used
by a library called coin, which is out of scope
of this course.
6. Dagger and Hilt: Dagger and a dagger is
dependency injection library, which makes easier implementing
the dependency injection. It reduces a lot of boilerplate code while
implementing dependency injection. Q is also dependency
injection library, which is built on top of dagger and it makes easier
using dagger. How it works. Dagger use annotation
processor to parse the code, to identify where to inject dependencies and what kind of
dependencies are required. Then dagger generate source code which is compiled by compiler. Here is dependency
injection library, which is built on top of dagger. It allows to write
less code by having predefined containers
for Android classes also makes easier injecting
dependencies into view model and
injecting view model itself.
7. Code: Code for this course is
available in the following URL. If you open that URL, you can find code
repository on GitHub, which contains code for simple weather
forecast application. In order to clone
this repository, click Code, click here to copy the URL and
open Android Studio. In Android Studio, click File. New Project from
version control. Here, paste the URL
which we copied. And here you should set the directory where you want to save the project
and click Clone. After cloning the code, you can run this application
on your device or emulator.
8. Without Dependency Injection: In this video, I will show code without
dependency injection. Let's open up Android Studio. We have already cloned
code from the repository. And now we are in master branch. We need to check
out no DI branch. This branch contains code
without dependency injection. First of all, let's open
AndroidManifest.xml. Here we can see it has one permission for
internet connection, uses clear text traffic
is sent through to be able to use HTTP connection. And we have one screen
called Forecast activity. In forecast activity,
we are creating instances of retrofit
using base URL. And we're setting our
JSON converter factory in order to convert
JSon data to object. In the end, we are creating
instance of API interface. In onCreate method, we are setting a layout XML
as content view. Let's open it. Here we have one recycler
view to show forecast data. Then we are calling jet forecast method to
get weather forecast. In jet forecast method, we are creating co-routine
to get weather forecast. And then we are switching two main dispatcher to
show weather forecast. In short forecast method, we are setting location
name is title, and then checking if daily
forecast data is available. If it's not null, we are setting layout
manager for recycler view. And then we are setting
forecasts adapter. The adapter receives
forecast data and sets it to the layout, which is list item forecast. It contains three,
takes two years to show date, temperature,
and condition. In build gradle file
dependencies for retrofit and dishonor converter
libraries have been added. Let's open API interface. And it includes one function which returns
forecasts, response, forecast response
campaigns, current daily location information
for the forecast data. Now, let's run this application
and see the result. Here you can see the
application which shows location name in title and weather
forecast data as a list.
9. With Dependency Injection: In this video, we will see code with dependency injection. In previous video, we
have seen code without dependency injection
where we create an instance of API in
forecast activity. So API is dependency and
forecast activity is dependent. Now let's switch to
branch called DI, which contains code with
dependency injection. In order to use here library, it should be added
to the project. Let me show how it
has been added. First of all, let's
open build gradle file. Here we can see that plug-in for HIV library has been added. Let's open Build Gradle
file for app module. And plug-in for his
library was applied. Also, we need to add Kotlin annotation processor
in order to use heal library. Made sure that project uses Java 1.8 as healed requires it. Then we add dependency
for healed library. And we add this to allow
references to generate code. Next step is to create
class called App, which extends application and annotated healed Android app. This annotation tells heel to generate dependency
injection code. Open AndroidManifest.xml
and declare application using
name attribute. Inside the IP packet, we create a module class
which is annotated with installed in and
module annotations. Inside this module we create function which is
annotated with provides a patient and it
provides API instance which will be injected
in forecast activity. Forecast activity
is annotated with Android entry point to
inject dependencies into it. Here we are injecting
instance of a guy with Inject annotation. So we're not creating it
inside forecast activity. Now, let's run this code
and see the result. Here we can see the
same application, but this time we implemented
dependency injection.
10. Hilt workflow: In this video, I will
show how health works. Let's start with AP class, which extends application and uses healed Android
app annotation. Annotation tells
here to generate dependency injection code
including singleton component. Singleton component is application level
dependency container, which injects dependencies. In App Model class, we are using module
annotation to tell him that app module
provides dependencies installed in annotation
is used to tell to which component app module
provides dependencies. In this case, a module provides dependencies for
singleton component, which is application level
dependency container. App module provides
dependency as instance of API using
provides annotation. In forecast activity Android
entry point annotation is used to create
activity component, which is child of
singleton component. So this means that
activity component for forecasts activity has access to dependencies to
singleton component. By using Inject annotation, we can inject instance of API. The overall workflow looks
like this app module provides instance of API
to singleton component. Activity component of forecast
activity has access to singleton component
dependencies and injects dependencies instance of API
using Inject annotation.
11. ViewModel: In this video, I
will show how to inject dependencies
into view model. First of all, let's
open up modules, build gradle file
and add dependency for Kotlin extensions
for activity artifacts. Inside forecast view model, we create mutable LiveData
for forecast response. And we create LiveData, which will be observed
by forecast activity. When forecasting
model is initialized. Yet forecast method is called. Forecast method creates
coroutine, which is cleared. When this view model is cleared. Insights is coroutine scope. We get the forecast data and
update mutable LiveData. In forecast activity, we inject forecast view model by not
using Inject annotation, but using ViewModel
provider API. Otherwise, we would have multiple instances
of view model. Here we set observer for
weather forecast data, which calls show forecast
method on Update. Now, let's run this application
and see the result. As you can see it's working. But this time we
are getting data in view model
instead of activity.
12. Binds: In this video, I will show
how to use binds annotation. Now we create data repository, which serves as a
single data source. For this purpose, we
create interface called repository with one
function, get forecast. It's suspend function which
returns forecast response. We create a class called
repository impulse, which is implementation
of repository interface. And it receives API instance to implement get
forecast method. In app module class, we create function
which provides repository
implementation instance when repository is requested. Not here we are getting
instance of API and busing to the
repository implementation. In previous videos, we use provides annotation to
provide dependency. But in this video, I would like to show another
way to provide dependency. For this purpose, we create
another module which provides dependencies
for singleton component. And in this case, we use binds sanitation
to provide dependency. Here we create a new
function which provides repository
implementation instance when repository is requested. When we use binds sanitation, implementation of function
is provided by hilt. In repository implementation, we enable this code snippet to be able to inject API when
we use binds sanitation, implementation of function
is provided by health. That's why we need to
use Inject annotation in constructor function to
inject instance of API. In forecast you model, we inject repository
instead of API, it serves a single
source of data. Now, let's run this application
and see the result. As we can see, it's
working in the same way. But this time we used repository as a single
source of data. And also we use buy-in
sanitation to bind dependency.
13. Singleton: In this video, I will
show how to provide same instance when
dependency is requested. Module provides dependencies
for singleton component and it creates instances every time when dependency
is requested. In order to check this, we can inject instance of
API and login as a string. We do the same thing in
repository in bulk class. Now let's run this code
and see the result. You feel open logcat, we can see that instances
of API are not same. In order to make up
module to return the same instance every time we can use singleton annotation. This annotation tells
healed to create only one instance in singleton component
dependency container. Now let's run this code
and see the result. This time we can see
that instances are same.
14. Context: In this video, I will show
how to inject context. First of all, we need
to add dependency for http interceptor,
color checker. In app module, we
create instance of chakra interceptor,
which requires context. We can get context using
application contexts annotation. Then we inject chocolate
interceptor into function where we create an instance
of a OK HTTP client. Then we provide a HTTP client into a function where we
create instance of retrofit. Now, let's run this code
and see the result. After running, open
the navigation drawer and click on notification, which says recording
is GTP activity. And here we can see the list of requests which has been
sent to the backend.
15. Named: In this video, I will
show how to provide instances of same type
with name it annotation. First of all, open up modules
built Gradle file and add dependency for HTTP
logging interceptor. This library logs HTTP
requests in logcat. Then open up module
class and add function, which provides another
login interceptor. And now we're providing two
instances of same time. Interceptor. When we inject dependency, heel should know which instance
we would like to inject. For this purpose named
annotation is used. Here we are setting name it annotation with login
interceptor key. For Tucker interceptor,
we are using name and annotation with
http interceptor key. When we are getting
those instances, we should use same
annotation with same key. And here we are setting to HTTP interceptors
for HTTP client. Now let's run this application
and see the result. Now, we can see log for
HTTP requests in logcat.
16. Qualifier: In this video, I will show
another way how to provide instances of same type
using custom annotations. In app module file, we create two custom annotations using qualifier annotation. Using retention
annotation, we make this annotation to be stored
in binary output. And we create annotations, http interceptor and
login interceptor. Here we provide
instances of interceptor using custom annotations
instead of name ID annotation. Also we replace name
it annotation with custom annotation when
we get those instances. Now, let's run this application
and see the result. And we can see same result, log of HTTP requests in logcat.
17. Component: In this video, we will
talk about components. One of the advantages
of healed library, it contains predefined
components. Components are dependency containers which
injects dependencies. Each component is bound to some lifecycle in
Android application. Here we can see hierarchy of components and main component
is singleton component. It is available throughout
whole application. It's created when
application is created, it's destroyed when
application is destroyed. Same applies to other
components, e.g. activity component
is created when activity is created
and destroyed. When activity is destroyed. This is useful when we need dependency only in one activity, not in whole application. According to this hierarchy, dependencies of
singleton component are available for
activity component, but dependencies of
activity component are not available for
singleton component or other components like ViewModel component because
it is sibling component. Annotation above, each
component is used to provide single instance
of dependency, e.g. singleton annotation for
singleton component or activity sculpt annotation is used for activity component. Let's create a new
module which provides dependencies for
activity component. First of all, open at modules, built Gradle file and add
dependency for Picasso library. It's used to load image. Then in list item forecast XML, we add new imageView to show
icon for weather condition. Then we create new interface
called image loader, which has one function to load the image from URL into imagery. After that, we create
implementation of image loader called
Picasso image loader, and it implements
load image function by using Picasso library. After that, we create new model called activity module,
which provide dependencies. For activity component. It has one function and it provides because
so image loader, when image loader is requested. Here we are using
activity sculpt annotation to use one
instance of image loader. In forecast activity,
we are injecting image loader and passing
into forecasts adapter. In forecast adapter, we
get that image loader and use it to load the image
from URL into ImageView. Let's run this code
and see the result. As we can see now, it's showing icons for weather
forecasts, conditions.
18. Thank you: This is the end of this
course where you learn what dependency and
dependency injection. You will learn how to set
up healed to implement dependency injection using
different futures of hailed. As a bonus, I would
like to provide interview questions on
dependency injection and healed. It's PDF file with questions
and answers and you can download it from resources
section of this video. I would like to thank you
for watching this course. I hope you liked it and see
you in my next courses.