如何在可组合项中使用 hilt 注入单例

use*_*435 16 android kotlin android-jetpack-compose

我正在尝试注入一个在可组合项内的 hiltmodule 中定义的单例类。我知道如何注入视图模型,但是单例类呢?

@Inject
    lateinit var mysingleton: MySingletonClass
Run Code Online (Sandbox Code Playgroud)

这段代码在活动中运行良好,但将其从活动转移到使用它的可组合项还有很长的路要走......还有更好的解决方案吗?

Dis*_*Dev 22

您不应该将依赖项注入到函数中,这就是@Composable。您可能希望将它们注入到 ViewModel 或 Activity 中。

如果您需要访问 @Composable 内的 ViewModel 范围(或应用程序范围)单例,则可以将该单例注入到 ViewModel 中,然后从 @Composable 访问 ViewModel。

您可以通过在 ViewModel hilt 模块中将该对象的提供程序函数注释为 @ViewScoped 来将该单例注入到 ViewModel 中。

如果您想要整个应用程序使用单例,而不是每个 ViewModel 实例使用单例,您可以将提供程序安装到 SingletonComponent::class 中并将其注释为 @Singleton。更多信息请点击这里

希尔特模块文件

@Module
@InstallIn(ViewModelComponent::class)
object ViewModelModule {

    @ViewScoped
    @Provides
    fun provideMySingleton(): MySingletonClass = MySingletonClass()
}
Run Code Online (Sandbox Code Playgroud)

您的 ViewModel 类:

@HiltViewModel
class MyViewModel
@Inject constructor(
    val mySingleton: MySingletonClass
): ViewModel() {

...

}
Run Code Online (Sandbox Code Playgroud)

您的 @Composable 函数:

@Composable fun DisplayPrettyScreen() {
...
    val viewModel: MyViewModel = hiltViewModel()
    val singleton = viewModel.mySingleton  //no need to assign it to a local variable, just for explanation purposes

}
Run Code Online (Sandbox Code Playgroud)

  • 从技术上讲,您可以做到这一点,但视图模型旨在成为状态持有者,而不是依赖持有者! (4认同)

小智 8

我也认为这是不可能的,但后来找到了方法......尝试了一下,似乎可行。

定义您的入口点接口:

private lateinit var dataStoreEntryPoint: DataStoreEntryPoint

@Composable
fun requireDataStoreEntryPoint(): DataStoreEntryPoint {
    if (!::dataStoreEntryPoint.isInitialized) {
        dataStoreEntryPoint =
            EntryPoints.get(
                LocalContext.current.applicationContext,
                DataStoreEntryPoint::class.java,
            )
    }
    return dataStoreEntryPoint
}

@EntryPoint
@InstallIn(SingletonComponent::class)
interface DataStoreEntryPoint {
    val dataStoreRepo: DataStoreRepo
}
Run Code Online (Sandbox Code Playgroud)

DataStoreRepo 是 Hilt 中定义的单例

@Singleton
    @Provides
    fun provideDataStoreRepository(dataStore: DataStore<Preferences>): DataStoreRepo =
        DataStoreRepo(dataStore)
Run Code Online (Sandbox Code Playgroud)

然后在可组合项中使用:

@Composable
fun ComposableFuncionName(dataStoreRepo: DataStoreRepo = requireDataStoreEntryPoint().dataStoreRepo){
...
}
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的答案。@DissidentDev 问题是关于注入 Singleton。可组合项中可能需要其他依赖项(不是存储库),但与业务逻辑无关,也不是体系结构的一部分。 (3认同)