kotlin 如何在组合物内部使用刀柄注入单例

ny6fqffe  于 2023-05-01  发布在  Kotlin
关注(0)|答案(2)|浏览(147)

我试图将一个定义在hiltmodule中的单例类注入到一个composable中。我知道如何注入视图模型,但单例类呢?

@Inject
    lateinit var mysingleton: MySingletonClass

这段代码在活动中可以正常工作,但是将它从活动携带到使用它的可组合对象是一段很长的路。有更好的解决办法吗

rvpgvaaj

rvpgvaaj1#

你不应该将依赖注入到一个函数中,这就是@Composable。您可能希望将它们注入到ViewModel或Activity中。
如果您需要访问@Composable中的ViewModel作用域(或Application作用域)单例,则可以将该单例注入ViewModel,然后从@Composable访问ViewModel。
您可以通过在ViewModel hilt模块中将该对象的provider函数注解为@ViewScoped来将该单例注入ViewModel中。
如果你想为整个应用程序使用一个单例,而不是每个ViewModel示例使用一个单例,你可以将提供程序安装到SingletonComponent::类中并将其注解为@Singleton。更多信息在这里。

Hilt模块文件

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

    @ViewScoped
    @Provides
    fun provideMySingleton(): MySingletonClass = MySingletonClass()
}

您的ViewModel类:

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

...

}

您的@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

}
fdbelqdn

fdbelqdn2#

我也认为这是不可能的,但后来找到了办法。试过了,似乎有效。
定义入口点接口:

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
}

DataStoreRepo在Hilt中定义为单例

@Singleton
    @Provides
    fun provideDataStoreRepository(dataStore: DataStore<Preferences>): DataStoreRepo =
        DataStoreRepo(dataStore)

然后在组合中使用:

@Composable
fun ComposableFuncionName(dataStoreRepo: DataStoreRepo = requireDataStoreEntryPoint().dataStoreRepo){
...
}

相关问题