英文:
Why can I reference Application in ViewModel when I use Hilt in Android Studio?
问题
I use Hilt as DI in Android Studio project. I know "A ViewModel must never reference a view, Lifecycle, or any class that may hold a reference to the activity context."
So you can find that there is a warning information in Image A for Code A.
But the ViewModelComponent
of Hilt has bound Application
, you can see the article.
1: I don't know why private val appContext: Application
in ViewModel doesn't display warning information, does it mean I can use Application
in ViewModel
when I use Hilt? could you tell me?
2: BTW, private val appContext: Application
displays the information below, why?
Constructor parameter is never used as a property
英文:
I use Hilt as DI in Android Studio project. I know "A ViewModel must never reference a view, Lifecycle, or any class that may hold a reference to the activity context."
So you can find that there is a warning information in Image A for Code A.
But the ViewModelComponent
of Hilt has bound Application
, you can see the article.
1: I don't know why private val appContext: Application
in ViewModel doesn't display warning information, does it mean I can use Application
in ViewModel
when I use Hilt? could you tell me?
2: BTW, private val appContext: Application
displays the information below, why?
Constructor parameter is never used as a property
Code A
@HiltViewModel
class RecordSoundViewModel @Inject constructor(
@ApplicationContext private val myContext: Context, //Android Studio displays warning information
private val appContext: Application, // Why doesn't it dsiplay warning information
private val savedStateHandle: SavedStateHandle
): ViewModel()
{
...
}
答案1
得分: 2
以下是您要翻译的内容:
可能只是lint看到ViewModel()中有Context并抱怨它。因为您可能提供了一个比ViewModel寿命更短的Context。
class MyViewModel: ViewModel() {
//将抱怨泄漏的context
val ctx: Context = Context()
}
将使用ApplicationContext注入到ViewModel中是一个有效的用例。
@Module
@InstallIn(SingletonComponent::class)
object WorkManagerModule {
@Provides
@Singleton
fun provideWorkManager(@ApplicationContext context: Context): WorkManager {
return WorkManager.getInstance(context)
}
}
@HiltViewModel
class MyViewModel @Inject constructor(
val workManager: WorkManager
)
对于第2点:Lint建议您删除private val。由于您未将其用作属性,val/var是不需要的。
@HiltViewModel
class MyViewModel @Inject constructor(
savedStateHandle: SavedStateHandle
) {
//不会抱怨属性
val myId = savedStateHandle.get<String>("MyId")
}
如果要将其用作属性,您必须添加val/var。
@HiltViewModel
class MyViewModel @Inject constructor(
savedStateHandle: SavedStateHandle
) {
fun getMyIdFromSaveState(): String? {
//将抱怨它不知道savedStateHandle,您必须添加val或var。
return savedStateHandle.get<String>("MyId")
}
}
英文:
It might just be the lint seeing Context inside a ViewModel() and complaining about it. Because you might be giving a Context that lives shorter than the ViewModel.
class MyViewModel: ViewModel() {
//will complain about leaking context
val ctx: Context = Context()
}
Injecting something that uses ApplicationContext into a ViewModel is a valid use case.
@Module
@InstallIn(SingletonComponent::class)
object WorkManagerModule {
@Provides
@Singleton
fun provideWorkManager(@ApplicationContext context: Context): WorkManager {
return WorkManager.getInstance(context)
}
}
@HiltViewModel
class MyViewModel @Inject constructor(
val workManager: WorkManager
)
For 2: Lint is telling you to remove private val. Since you are not using it as a property, val/var is not needed.
@HiltViewModel
class MyViewModel @Inject constructor(
savedStateHandle: SavedStateHandle
) {
//not complaints about property
val myId = savedStateHandle.get<String>("MyId")
}
If you want to use it as a property you must add val/var.
@HiltViewModel
class MyViewModel @Inject constructor(
savedStateHandle: SavedStateHandle
) {
fun getMyIdFromSaveState(): String? {
//will complain that it does not know savedStateHandle, you must add val or var.
return savedStateHandle.get<String>("MyId")
}
}
答案2
得分: 0
尝试使用以下的 AndroidViewModel
:
@HiltViewModel
class RecordSoundViewModel @Inject constructor(
private val appContext: Application,
): AndroidViewModel(appContext) {
....
}
在初始化 Fragment/Activity 中的 viewModel 时,无需传递应用程序引用:
private val viewModel: RecordSoundViewModel by viewModels()
英文:
Try AndroidViewModel
as follow:
@HiltViewModel
class RecordSoundViewModel @Inject constructor(
private val appContext: Application,
): AndroidViewModel(appContext) {
....
}
No need to pass application reference in when initializing viewModel in Fragment/Activity
private val viewModel : RecordSoundViewModel by viewModels()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论