Skip to content

Android Hilt Fragment — Complete Guide

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about Android Hilt Fragment. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

The Problem

Your Fragment's injected fields are null, or you share a ViewModel between parent and child fragments but get different instances.

Wrong Approach ❌

// Missing @AndroidEntryPoint
class MyFragment : Fragment() {
    @Inject lateinit var repo: UserRepository // Always null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        repo.loadUsers() // NPE!
    }
}
// Incorrect ViewModel scoping
class ParentFragment : Fragment() {
    private val vm: SharedViewModel by viewModels()
}

class ChildFragment : Fragment() {
    // Gets its OWN instance, not parent's
    private val vm: SharedViewModel by viewModels()
}

Output: Null injection. Separate ViewModel instances when sharing should occur.

Right Approach ✅

@AndroidEntryPoint
class MyFragment : Fragment() {
    @Inject lateinit var repo: UserRepository
    @Inject lateinit var analytics: AnalyticsService

    // ViewModel scoped to this fragment
    private val vm: UserViewModel by viewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // Hilt has already injected fields
        repo.loadUsers()
        analytics.logScreenView("MyFragment")
    }
}

// Shared ViewModel with parent fragment
@AndroidEntryPoint
class ChildFragment : Fragment() {
    // Gets the parent fragment's ViewModel
    private val vm: SharedViewModel by viewModels(
        ownerProducer = { requireParentFragment() }
    )
}

// Or scoped to Activity
@AndroidEntryPoint
class MyFragment : Fragment() {
    private val vm: SharedViewModel by activityViewModels()
}

Output: Injected dependencies available immediately. Proper ViewModel scoping.

Prevention

  • Always annotate Fragments with @AndroidEntryPoint.
  • Use by viewModels(ownerProducer = { requireParentFragment() }) for parent-scoped VM.
  • Use by activityViewModels() for Activity-scoped VM.
  • Access injected fields after super.onViewCreated().

Common Mistakes with hilt fragment

  1. Mixing let bindings with <- bindings in do notation, producing type errors
  2. Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
  3. Non-exhaustive pattern matches that compile with warnings then crash at runtime

These mistakes appear frequently in real-world Android code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

### Can I inject a ViewModel into a Fragment without @AndroidEntryPoint?

No. Hilt needs @AndroidEntryPoint to set up the Fragment component. Without it, viewModels() won't inject constructor dependencies.

### How do I scope a ViewModel to the navigation graph?

Use by hiltViewModel() (for Hilt) or by viewModels() with a NavBackStackEntry owner. Hilt automatically scopes to the navigation destination.

### What is the difference between by viewModels() and by activityViewModels()?

viewModels() scopes to the current Fragment. activityViewModels() scopes to the hosting Activity, enabling sharing between fragments of the same Activity.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro