你可以在使用Hilt在Android Studio时在ViewModel中引用Application吗?

huangapple go评论61阅读模式
英文:

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()
{
     ...
}

Image A
你可以在使用Hilt在Android Studio时在ViewModel中引用Application吗?

答案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&lt;String&gt;(&quot;MyId&quot;)
}

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&lt;String&gt;(&quot;MyId&quot;)
    }
}

答案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()

huangapple
  • 本文由 发表于 2023年5月21日 10:14:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76298028.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定