android : @AndroidEntryPoint and @HiltViewModel usage

 @AndroidEntryPoint is an annotation used in Hilt, which is Google’s recommended library for Dependency Injection (DI) built on top of Dagger.

What does it actually do?

When you mark a class with @AndroidEntryPoint, Hilt generates an individual Hilt component for that specific Android class (in this case, your MainActivity).

Member Injection: It allows the class to receive dependencies from Hilt. Without this, you couldn't use the @Inject annotation to get your ViewModels, Repositories, or API services into the Activity.

Lifecycle Management: It ensures that the dependencies are tied to the Activity's lifecycle. Hilt will automatically handle creating the component in onCreate() and destroying it when the Activity is destroyed.

There are a few things to remember how to use this. We need to use viewModel delegate


@dagger.hilt.android.AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val viewModel: HomeViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
GetMyHomeTheme {
GetMyHomeApp(viewModel = viewModel)
}
}
}
}


How the "Chain" works

When you call by viewModels(), Hilt does the following behind the scenes:

  1. Lookups: It looks at the HomeViewModel constructor.

  2. Fulfillment: It sees it needs PropertySearchBackendApi and OkHttpClient.

  3. Search: It searches your Hilt Modules (classes marked with @Module) to find instructions on how to create those specific objects.

  4. Delivery: It creates the objects, creates the ViewModel, and hands it to your Activity.


@HiltViewModel // <--- Use this for ViewModels
class HomeViewModel @Inject constructor(
private val propertySearchBackendApi: PropertySearchBackendApi,
private val graphQLClient: OkHttpClient
) : ViewModel() { ... }


Can you have more than one AndroindEntry point - Yes you can 

Here is a full example, we will create DetailActivity, then define the DetailScreen and finally DetailViewModel


@AndroidEntryPoint
class DetailActivity : ComponentActivity() {
private val viewModel: DetailViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
GetMyHomeTheme {
DetailScreen(viewModel = viewModel)
}
}
}
}

And then we will have our DetailScreen here. This is our main layout and it should contains all our UI, at this point it is just a Button that calls viewModel.sayHi(). 

@Composable
fun DetailScreen(viewModel: DetailViewModel) {
Box(
modifier = Modifier
.fillMaxSize()
.background(BackgroundDark),
contentAlignment = Alignment.Center
) {
Text(
text = "Detail Screen",
color = TextPrimary,
fontSize = 24.sp
)
Button(
onClick = { viewModel.sayHi() }, <---- calling view model function sayHi()
modifier = Modifier
.fillMaxWidth()
.height(56.dp),
colors = ButtonDefaults.buttonColors(
containerColor = PrimaryPurple
),
shape = RoundedCornerShape(12.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
)
{
Text("Detail View", fontSize = 16.sp, fontWeight = FontWeight.Medium)
}
}
}
}


And finally our view model 

@HiltViewModel

class DetailViewModel @Inject constructor(
private val propertySearchBackendApi: PropertySearchBackendApi,
private val graphQLClient: OkHttpClient
) : ViewModel() {

fun sayHi()
{
val test = propertySearchBackendApi.toString()
}
}


Comments