Open In App

Dagger Hilt in Android with Example

Last Updated : 31 May, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Dependency Injection (DI) is a design pattern to decouple the conventional dependency relationship between objects. When it comes to DI in android Dagger always takes a lead. But it is very complex and requires a lot of boilerplate codes in order to set up the Dagger. So, to overcome this problem Hilt was introduced. Dagger Hilt simplifies the whole process and reduces the unnecessary steps without losing any of the features of the original Dagger.

Example

In this example, we will build an android application that will show the list of cryptocurrencies using the MVVM design pattern and for dependency injection, we will be using Dagger Hilt.

Step 1: Create a New Project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Kotlin as the programming language.

Step 2: Adding dependencies

In order to use Dagger Hilt, we need to add the dependencies for it. First, we will add the classpath to our project-level build.gradle file. For adding this dependency Go to Gradle Scripts > build.gradle(Project:app) add the following dependency. After adding these dependencies you need to click on Sync Now.

dependencies {
        classpath 'com.google.dagger:hilt-android-gradle-plugin:2.38.1'
    }

Now, in the app-level build.gradle file we need to place a plugin. For this, Go to Gradle Scripts > build.gradle(Module:app) add the following plugin.

plugins {
    id 'kotlin-android'
    id 'kotlin-kapt'
    id 'dagger.hilt.android.plugin'
}

We also need to add the dependency in the same app-level build.gradle file. Following dependency needs to be added inside the build.gradle(Module:app).

dependencies {
    implementation 'com.github.bumptech.glide:glide:4.9.0'
    implementation 'com.google.dagger:hilt-android:2.38.1'
    kapt 'com.google.dagger:hilt-android-compiler:2.38.1'
    kapt 'androidx.hilt:hilt-compiler:1.0.0'
    implementation "androidx.activity:activity-ktx:1.4.0"
}

We also need to add property attributes in gradle.properties file. Go to Gradle Scripts > gradle.properties and add the following property.

kapt.use.worker.api=false

After adding plugins and dependencies you need to click on Sync Now. Before moving further let’s add some color attributes in order to enhance the app bar. Go to app > res > values > colors.xml and add the following color attributes. 

XML




<resources>
    <color name="colorPrimary">#0F9D58</color>
    <color name="colorPrimaryDark">#16E37F</color>
    <color name="colorAccent">#03DAC5</color>
</resources>


Step 3: Creating An HiltApplication Class

In this step, we will create an HiltApplication.kt class and annotate this class with @HiltAndroidApp annotations. This will make this class trigger Hilt’s code generation which will have the base class for our application and it acts as the application-level dependency container. For this go to app > java > package > right-click > New > Kotlin Class/File and name it as HiltApplication.

Kotlin




import android.app.Application
import dagger.hilt.android.HiltAndroidApp
 
@HiltAndroidApp
class HiltApplication :Application(){
}


Once we are done with this, we need to update our AndroidManifest.xml file by providing our HiltApplication.kt class name as android:name inside <application></application> tag. Also, we need to add Internet permission in the AndroidManifest file.

XML




<uses-permission android:name="android.permission.INTERNET" />
 
<application
        android:name=".HiltApplication" >
</application>


Step 4: Creating Data Class And A Repository

In this step, first, we will create a Data class and name it Cryptocurrency. This class will have two member variable images and a name. For this Go to app > java > package > Right-click > New > Kotlin Class/File.

Kotlin




data class Cryptocurrency(
    val image:String,
    val name:String
)


Now, we will create a Repository class that will have a few sample data which we will inject into our ViewModel. We will make this Repository abstract by making it an interface and providing an implementation to it. For creating this Go to app > java > package > Right-click > New > Kotlin Class/File and make its type as interface and give its name as CryptocurrencyRepository and add the following interface code to it.

Kotlin




interface CryptocurrencyRepository {
    fun getCryptoCurrency(): List<Cryptocurrency>
}


Now, we will provide an implementation to this interface class. For this Go to app > java >  package > Right-click > New > Kotlin Class/File and create a new class and name it as CryptocurrencyRepositoryImpl.kt, In this class we will override the getCryptoCurrency() method and provide an implementation to it. The cryptocurrency data class will have two string type attributes one for image and the other for the name.

Kotlin




class CryptocurrencyRepositoryImpl : CryptocurrencyRepository{
    // Overriding the interface method and
    // providing implementation to it
    override fun getCryptoCurrency() = listOf(
        // here we are adding images from wikipedia
        Cryptocurrency("https://upload.wikimedia.org/wikipedia/en/d/d0/Dogecoin_Logo.png", "DogeCoin"),
    )
}


Step 5: Creating A Module Class

In this step, we will create a module class and name it as AppModule. For this Go to app > java >  package > Right-click > New > Kotlin Class/File and create a new class and name it as AppModule.kt. AppModule class will inject dependency to other classes so, we need to annotate this class with @Module annotation which will make this class a module to inject dependency to other classes within its scope. Furthermore, we will also add one more annotation to it. i.e., @InstallIn(SingletonComponent::class) this will make this class inject dependencies across the entire application.

Kotlin




import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
 
// @Module annotation which will make this class a module
// to inject dependency to other class within it's scope.
// @InstallIn(SingletonComponent::class) this will make
// this class to inject dependencies across the entire application.
@Module
@InstallIn(SingletonComponent::class)
class AppModule {
    @Provides
    @Singleton
    fun provideCryptocurrencyRepository():CryptocurrencyRepository=CryptocurrencyRepositoryImpl()
}


Here, we have also added the provision for CryptocurrencyRepository using @Provides annotation. Along with this, we have used @Singleton annotation so that whenever we inject the dependency we inject the same single instance of CryptocurrencyRepository were ever requested.

Step 6: Creating  A ViewModel

In this step, we will create a ViewModel. In order to do so,  Go to app > java > package > Right-click > New > Kotlin Class/File and create a new class and name it as MainViewModel.kt. We will annotate it with @HiltViewModel which makes the models to be created using Hilt’s model factory that makes it easier to be used with Activities and Fragments. We will also annotate exactly one constructor with @Inject annotation, using this constructor we will inject all the dependencies to our view model class. Below is the code for MainViewModel.kt class.

Kotlin




import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
 
// @HiltViewModel will make models to be
// created using Hilt's model factory
// @Inject annotation used to inject all
// dependencies to view model class
@HiltViewModel
class MainViewModel @Inject constructor(
    private val cryptocurrencyRepository: CryptocurrencyRepository
) : ViewModel() {
    private val cryptocurrencyEmitter = MutableLiveData<List<Cryptocurrency>>()
    val cryptoCurrency: LiveData<List<Cryptocurrency>> = cryptocurrencyEmitter
    init {
        loadCryptocurrency()
    }
     
    // getting cryptocurrencies list using
    // repository and passing it into live data
    private fun loadCryptocurrency() {
        cryptocurrencyEmitter.value = cryptocurrencyRepository.getCryptoCurrency()
    }
}


Step 7: Create An Adapter Class

In this step, we will create an adapter. In order to do so, Go to app > java > package > Right-click > New > Kotlin Class/File and create a new class and name it as CryptocurrencyAdapter.kt. This will provide access to our cryptocurrency data items and be responsible for making a View for each item in the cryptocurrency data list.

Kotlin




import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
 
class CryptocurrencyAdapter(private val cryptocurrency: List<Cryptocurrency>) : RecyclerView.Adapter<CryptocurrencyAdapter.ViewHolder>()  {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        // Inflating list data from list_item to view
        val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
        return ViewHolder(view)
    }
    // Binding cryptocurrency list to ViewHolder
    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(cryptocurrency[position])
    }
    override fun getItemCount() = cryptocurrency.size
    // Iterating ViewHolder and loading it's
    // content to our Image and Text ViewsT
    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(index: Cryptocurrency) {
            // Here, we are using Glide library to
            // load the image into ImageView
            Glide.with(itemView.context)
                .load(index.image).dontAnimate()
                .into(itemView.findViewById(R.id.image))
            // Setting name of cryptocurrency to TextView
            itemView.findViewById<TextView>(R.id.cryptocurrency).text = index.name
        }
    }
}


Step 8: Create list_item.xml File

In this step, we will create a list_item.xml file which will contain the views for our image and the name of the cryptocurrency. For this Go to app > res > layout >  Right-click > New > Layout Resource File and create a resource file and name it list_item.xml and add the following lines of codes to it.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="16dp"
    android:layout_margin="8dp"
    android:background="#f5f5f5"
    xmlns:tools="http://schemas.android.com/tools"
   
    <ImageView
        android:id="@+id/image"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:scaleType="fitXY"
        android:layout_margin="24dp"
        android:importantForAccessibility="no"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />
   
    <!--text used are only for understanding purpose it
        will be removed at the runtime-->
    <TextView
        android:id="@+id/cryptocurrency"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="24dp"
        android:textSize="24sp"
        app:layout_constraintStart_toEndOf="@id/image"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        tools:text="Cryptocurrencies" />
   
</androidx.constraintlayout.widget.ConstraintLayout>


Step 9: Create activity_main.xml File

In this step, we will make the layout for our activity_main.xml file. We will just add a RecyclerView to our layout.

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
   
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/cryptocurrency_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
   
</androidx.constraintlayout.widget.ConstraintLayout>


Step 10: Working With MainActivity File

Finally, we work with our MainActivity. First, we annotate it with @AndroidEntryPoint annotation which will make the component class(activity, fragments, views, services, and broadcast receiver) ready for injection. Also, we will get our ViewModel in MainActivity by using by viewModles() delegate. After that, we are just observing our LiveData.

Kotlin




@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
   
      private lateinit var cryptocurrencyList: RecyclerView
   
    // viewModels() delegate used to get
    // by view models will automatically construct the viewmodels using Hilt
    private val viewModel:MainViewModel by viewModels()
     
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
         
          cryptocurrencyList = findViewById<RecyclerView>(R.id.cryptocurrency_list)
        cryptocurrencyList.layoutManager = LinearLayoutManager(this)
         
        observeCryptoCurrency()
    }
     
    // Observing the live data
    private fun observeCryptoCurrency() {
        viewModel.cryptoCurrency.observe(this) {
            cryptocurrencyList.adapter = CryptocurrencyAdapter(it)
        }
    }
}


Output:



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads