Inject context with Hilt: this field leaks a context object
Asked Answered
H

7

44

I'm using Hilt to inject context and other dependencies into my HomeViewModel class; Everything is working properly but I'm getting this warning. How can I prevent from leakings?

This is my HomeFragment (where I inject and use the HomeViewModel class):

@AndroidEntryPoint
class HomeFragment : Fragment() {

private val viewModel: HomeViewModel by viewModels()

....

}

This is the warning:

Hilt injection viewModel

class HomeViewModel @ViewModelInject constructor(
    @ApplicationContext val context: Context,
    private val locationAPI: LocationAPI,
    private val imagesAPI: ImagesAPI
) :
    ViewModel() {
...
}

I'm using:

//Hilt DI
implementation "com.google.dagger:hilt-android:2.30.1-alpha"
kapt "com.google.dagger:hilt-android-compiler:2.30.1-alpha"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02"
kapt "androidx.hilt:hilt-compiler:1.0.0-alpha02"

Thanks!

-- Edited, as suggested, after the first given answer:

The Home Fragment now is:

enter image description here

@HiltViewModel
class DetailsViewModel @Inject constructor(
    @ApplicationContext val context: Context,
    private val locationDetailsAPI: LocationAPI) :
    ViewModel() {
...

}

Dependencies updated to:

//Hilt DI
implementation "com.google.dagger:hilt-android:2.31-alpha"
kapt "com.google.dagger:hilt-android-compiler:2.30.1-alpha"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0-alpha03"

And I'm still getting this leaking error.

Any ideias?

Hallam answered 15/2, 2021 at 23:33 Comment(4)
If you need context why not just use AndroidViewModel? not sure about HILT leak though .Olodort
If you post images of code, please also copy/paste or type the actual code directly into the post. Please see Why may I not upload images of code on SO when asking a question?. Posts in which essential text is only included in images are likely to be closed for not having enough details.Fassold
Were you able to find a solution to this? I'm running into the same issue and I've tried updating the dependencies to the latest versions, but to no avail.Undergraduate
No, @WalterBerggren, I wasnt able. But I think you use this way is not a problem at all, check the last answer given to this post. The fellow made a test and assured this is no leak of memory and this is just a warning.Hallam
D
6

I don't get this warning, and I inject a context the same way.

Try updating to 2.31.2-alpha for hilt and 1.0.0-alpha03 for hilt-androidx

There are a few breaking changes. You will need to annotate your view models with @HiltViewModel, use @Inject instead of @ViewModelInject. And you will need to replace any references to ApplicationComponent with SingletonComponent.

Dishtowel answered 16/2, 2021 at 2:24 Comment(3)
Hi, I have updated the dependencies and changed the code, but I still get the warning. Any ideias of what I am missing?Hallam
Weird. Make sure you updated your hilt-android-gradle-plugin to 2.31.2-alpha.... Also, check if there's an update for Android studio. I am running 4.1.2Dishtowel
I am also running AS 4.2 and hilt version is 2.33-beta. Still the warning comes for me.Crossbar
W
22

After I faced that warning

enter image description here

I decided to profile memory to be guaranteed that the approach causes a memory leak, but what I found is quite interesting

enter image description here

yeah, there is no leak it's just a warning so don't care about it anymore, happy coding ;)

Whereinto answered 17/3, 2021 at 13:57 Comment(1)
I reached the same conclusion (I can't say for sure but since the app context will always outlive the activity context, there should be no leak)Dieball
W
9

Inject application instead:

@Inject constructor(private val application: Application)

Then you can get the app context like this:

application.applicationContext
Winfrid answered 12/12, 2021 at 11:27 Comment(0)
B
9

I think it's some kind of a false warning because Android studio cannot deduct that you're injecting an Application level context.

See the warning message details:

ViewModel classes should never point to Views or non-application Contexts.

Now try changing the constructor parameter name from context to applicationContext and warning is gone.

class HomeViewModel @ViewModelInject constructor(
    @ApplicationContext val applicationContext: Context,
    private val locationAPI: LocationAPI,
    private val imagesAPI: ImagesAPI
) :
    ViewModel() {
...
}

renaming context to applicationContext

Bathy answered 7/12, 2023 at 14:34 Comment(0)
D
6

I don't get this warning, and I inject a context the same way.

Try updating to 2.31.2-alpha for hilt and 1.0.0-alpha03 for hilt-androidx

There are a few breaking changes. You will need to annotate your view models with @HiltViewModel, use @Inject instead of @ViewModelInject. And you will need to replace any references to ApplicationComponent with SingletonComponent.

Dishtowel answered 16/2, 2021 at 2:24 Comment(3)
Hi, I have updated the dependencies and changed the code, but I still get the warning. Any ideias of what I am missing?Hallam
Weird. Make sure you updated your hilt-android-gradle-plugin to 2.31.2-alpha.... Also, check if there's an update for Android studio. I am running 4.1.2Dishtowel
I am also running AS 4.2 and hilt version is 2.33-beta. Still the warning comes for me.Crossbar
A
2

Your Kotlin plugin version is 1.4.30-release-Studio4.1-1?

If so, downgrade kotlin plugin version.

In 1.4.30-release-Studio4.1-1 version,

if viewmodel has context as instance variable, it causes warning.

Allix answered 17/2, 2021 at 7:35 Comment(0)
T
0

I had the same problem after updating Hilt dependencies.

It's right to use @HiltViewModel with @Inject before the constructor.

Regarding the leak due to the Context, just remove it from the ViewModel constructor, and pass the Context as method parameter of your functions, like this:

@HiltViewModel
class HomeViewModel @Inject constructor(
    private val locationDetailsAPI: LocationAPI,
    private val imagesAPI: ImagesAPI
) : ViewModel() { 

    fun getImages(context: Context) {
        // do something
    }
}
Titty answered 12/3, 2021 at 13:51 Comment(2)
Is passing it in the method parameter the right way?Chignon
I think this is not the best MVVM+Repository with Hilt practice with Context. Maybe there are other ways to use it better, or maybe not, I honestly don't know. But on second thought, using Context in this way you will avoid all memory leaks due to the Context because, always, the reference to the Context is destroyed after the method ends and GC is triggered.Titty
C
0

it should be safe here, There isn't really a leak here in the context constructor, it is just the lint check doesn't know that is the application context, and not some other context. and I think I think it'd be safe to suppress that warning too. to inspect the memory memory usage with Memory Profiler, read this documentation: https://developer.android.com/studio/profile/memory-profiler

Carlock answered 27/5, 2022 at 12:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.