<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Angel's Blog]]></title><description><![CDATA[Angel's Blog]]></description><link>https://blog.angelsaikia.com</link><generator>RSS for Node</generator><lastBuildDate>Thu, 09 Apr 2026 10:56:28 GMT</lastBuildDate><atom:link href="https://blog.angelsaikia.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Integrating Hilt Dependency Injection in Android Compose Applications]]></title><description><![CDATA[Introduction
Hilt is the recommended dependency injection library for Android, built on top of Dagger to simplify DI implementation. This guide will walk you through integrating Hilt in your Android Compose application, using practical examples from ...]]></description><link>https://blog.angelsaikia.com/integrating-hilt-dependency-injection-in-android-compose-applications</link><guid isPermaLink="true">https://blog.angelsaikia.com/integrating-hilt-dependency-injection-in-android-compose-applications</guid><category><![CDATA[Android]]></category><category><![CDATA[Jetpack Compose]]></category><category><![CDATA[compose]]></category><category><![CDATA[dagger-hilt]]></category><dc:creator><![CDATA[Angel Saikia]]></dc:creator><pubDate>Tue, 03 Jun 2025 15:30:19 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Hilt is the recommended dependency injection library for Android, built on top of Dagger to simplify DI implementation. This guide will walk you through integrating Hilt in your Android Compose application, using practical examples from a fitness tracking app.</p>
<h2 id="heading-setup">Setup</h2>
<h3 id="heading-1-add-dependencies">1. Add Dependencies</h3>
<p>First, add the required dependencies in your project's <code>build.gradle.kts</code> file:</p>
<pre><code class="lang-kotlin">plugins {
    id(<span class="hljs-string">"com.google.dagger.hilt.android"</span>)
    id(<span class="hljs-string">"kotlin-kapt"</span>)
}

dependencies {
    implementation(<span class="hljs-string">"com.google.dagger:hilt-android:2.48"</span>)
    kapt(<span class="hljs-string">"com.google.dagger:hilt-compiler:2.48"</span>)
    implementation(<span class="hljs-string">"androidx.hilt:hilt-navigation-compose:1.1.0"</span>)
}
</code></pre>
<h3 id="heading-2-create-application-class">2. Create Application Class</h3>
<p>Create a custom Application class and annotate it with <code>@HiltAndroidApp</code>:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@HiltAndroidApp</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApplication</span> : <span class="hljs-type">Application</span></span>()
</code></pre>
<p>Update your <code>AndroidManifest.xml</code> to use the custom Application class:</p>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">application</span>
    <span class="hljs-attr">android:name</span>=<span class="hljs-string">".MyApplication"</span>
    <span class="hljs-attr">...</span> &gt;</span>
</code></pre>
<h2 id="heading-dependency-injection-implementation">Dependency Injection Implementation</h2>
<h3 id="heading-1-creating-modules">1. Creating Modules</h3>
<p>Modules are classes that tell Hilt how to provide instances of different types. Here's an example of a network module:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Module</span>
<span class="hljs-meta">@InstallIn(SingletonComponent::class)</span>
<span class="hljs-keyword">object</span> NetworkModule {
    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideApiService</span><span class="hljs-params">()</span></span>: ApiService {
        <span class="hljs-keyword">return</span> Retrofit.Builder()
            .baseUrl(<span class="hljs-string">"https://api.example.com/"</span>)
            .addConverterFactory(GsonConverterFactory.create())
            .build()
            .create(ApiService::<span class="hljs-keyword">class</span>.java)
    }

    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideRepository</span><span class="hljs-params">(apiService: <span class="hljs-type">ApiService</span>, app: <span class="hljs-type">Application</span>)</span></span>: MyRepository {
        <span class="hljs-keyword">return</span> MyRepositoryImpl(apiService, app)
    }
}
</code></pre>
<h3 id="heading-2-implementing-viewmodels">2. Implementing ViewModels</h3>
<p>To use Hilt in ViewModels, annotate them with <code>@HiltViewModel</code> and inject dependencies:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@HiltViewModel</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HomeViewModel</span> <span class="hljs-meta">@Inject</span> <span class="hljs-keyword">constructor</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> repository: MyRepository
) : ViewModel() {
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> _uiState = MutableStateFlow(HomeUiState())
    <span class="hljs-keyword">val</span> uiState: StateFlow&lt;HomeUiState&gt; = _uiState.asStateFlow()

    <span class="hljs-keyword">init</span> {
        loadData()
    }

    <span class="hljs-keyword">private</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">loadData</span><span class="hljs-params">()</span></span> {
        viewModelScope.launch {
            <span class="hljs-keyword">try</span> {
                <span class="hljs-keyword">val</span> <span class="hljs-keyword">data</span> = repository.getData()
                _uiState.value = _uiState.value.copy(
                    <span class="hljs-keyword">data</span> = <span class="hljs-keyword">data</span>,
                    isLoading = <span class="hljs-literal">false</span>
                )
            } <span class="hljs-keyword">catch</span> (e: Exception) {
                _uiState.value = _uiState.value.copy(
                    error = e.message,
                    isLoading = <span class="hljs-literal">false</span>
                )
            }
        }
    }
}
</code></pre>
<h3 id="heading-3-using-in-composables">3. Using in Composables</h3>
<p>In your Composable functions, use <code>hiltViewModel()</code> to get an instance of your ViewModel:</p>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Composable</span>
<span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">HomeScreen</span><span class="hljs-params">(
    viewModel: <span class="hljs-type">HomeViewModel</span> = hiltViewModel()</span></span>
) {
    <span class="hljs-keyword">val</span> uiState <span class="hljs-keyword">by</span> viewModel.uiState.collectAsState()

    <span class="hljs-keyword">when</span> {
        uiState.isLoading -&gt; LoadingIndicator()
        uiState.error != <span class="hljs-literal">null</span> -&gt; ErrorMessage(uiState.error)
        <span class="hljs-keyword">else</span> -&gt; Content(uiState.<span class="hljs-keyword">data</span>)
    }
}
</code></pre>
<h2 id="heading-best-practices">Best Practices</h2>
<ol>
<li><p><strong>Scope Management</strong>: Use appropriate scope annotations:</p>
<ul>
<li><p><code>@Singleton</code> for application-wide instances</p>
</li>
<li><p><code>@ActivityScoped</code> for activity-level instances</p>
</li>
<li><p><code>@ViewModelScoped</code> for ViewModel-level instances</p>
</li>
</ul>
</li>
<li><p><strong>Testing</strong>: Hilt makes testing easier by allowing you to swap implementations:</p>
</li>
</ol>
<pre><code class="lang-kotlin"><span class="hljs-meta">@Module</span>
<span class="hljs-meta">@TestInstallIn(
    components = [SingletonComponent::class],
    replaces = [NetworkModule::class]
)</span>
<span class="hljs-keyword">object</span> TestNetworkModule {
    <span class="hljs-meta">@Provides</span>
    <span class="hljs-meta">@Singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">provideTestApiService</span><span class="hljs-params">()</span></span>: ApiService {
        <span class="hljs-keyword">return</span> FakeApiService()
    }
}
</code></pre>
<ol start="3">
<li><strong>Interface Abstraction</strong>: Always depend on interfaces rather than concrete implementations:</li>
</ol>
<pre><code class="lang-kotlin"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">MyRepository</span> </span>{
    <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getData</span><span class="hljs-params">()</span></span>: List&lt;Data&gt;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyRepositoryImpl</span> <span class="hljs-meta">@Inject</span> <span class="hljs-keyword">constructor</span></span>(
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">val</span> apiService: ApiService
) : MyRepository {
    <span class="hljs-keyword">override</span> <span class="hljs-keyword">suspend</span> <span class="hljs-function"><span class="hljs-keyword">fun</span> <span class="hljs-title">getData</span><span class="hljs-params">()</span></span>: List&lt;Data&gt; {
        <span class="hljs-keyword">return</span> apiService.getData()
    }
}
</code></pre>
<h2 id="heading-common-pitfalls">Common Pitfalls</h2>
<ol>
<li><p><strong>Circular Dependencies</strong>: Avoid circular dependencies between classes. Use <code>@Lazy</code> if necessary.</p>
</li>
<li><p><strong>Scope Mismatch</strong>: Ensure that dependencies have compatible scopes. A <code>@Singleton</code> component cannot depend on a <code>@ActivityScoped</code> component.</p>
</li>
<li><p><strong>Missing Bindings</strong>: Always provide all necessary dependencies in your modules.</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Hilt simplifies dependency injection in Android applications by reducing the boilerplate code and providing a standard way to implement DI. When used with Jetpack Compose, it creates a clean and maintainable architecture that's easy to test and scale.</p>
<p>Remember to:</p>
<ul>
<li><p>Keep modules focused and organized</p>
</li>
<li><p>Use appropriate scopes</p>
</li>
<li><p>Follow interface-based design</p>
</li>
<li><p>Write tests using Hilt's testing utilities</p>
</li>
</ul>
<p>By following these guidelines, you'll have a robust dependency injection setup in your Android Compose application.</p>
]]></content:encoded></item></channel></rss>