Kotlin中带参数的Singleton
上面说我可以使用object关键字创建一个singleton,如下所示:Kotlin中带参数的Singleton,kotlin,Kotlin,上面说我可以使用object关键字创建一个singleton,如下所示: object DataProviderManager { fun registerDataProvider(provider: DataProvider) { // } } 但是,我想向该对象传递一个参数。例如,Android项目中的ApplicationContext 有什么方法可以做到这一点吗?因为对象没有构造函数,所以我在初始设置中注入了以下值。您可以随意调用该函数,并且可以随时调用该函数来修改值(
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
//
}
}
但是,我想向该对象传递一个参数。例如,Android项目中的ApplicationContext
有什么方法可以做到这一点吗?因为对象没有构造函数,所以我在初始设置中注入了以下值。您可以随意调用该函数,并且可以随时调用该函数来修改值(或根据需要重新构造单例)
还有两个本机Kotlin注入库非常易于使用,并具有其他形式的单例,包括每线程、基于键等。不确定是否在您的问题的上下文中,但这里有指向这两个库的链接:
- Injekt(我的,我是作者):
- Kodein(类似于Injekt):
通常在Android中,人们使用这样的库,或Dagger等来完成单例的参数化、范围界定等。Kotlin有一个名为的功能,允许您将参数直接传递给对象
object DataProviderManager {
fun registerDataProvider(provider: String) {
//
}
operator fun invoke(context: ApplicationContext): DataProviderManager {
//...
return this
}
}
//...
val myManager: DataProviderManager = DataProviderManager(someContext)
我建议您使用此表单在Kotlin debit中的singleton中传递参数,说明构造函数中的对象被剥夺和阻止:
object Singleton {
fun instance(context: Context): Singleton {
return this
}
fun SaveData() {}
}
你在活动中这样称呼它
Singleton.instance(this).SaveData()
对于大多数现有答案,可以在不首先初始化单例的情况下访问类成员。下面是一个线程安全示例,确保在访问其任何成员之前创建一个实例
class MySingleton private constructor(private val param: String) {
companion object {
@Volatile
private var INSTANCE: MySingleton? = null
@Synchronized
fun getInstance(param: String): MySingleton = INSTANCE ?: MySingleton(param).also { INSTANCE = it }
}
fun printParam() {
print("Param: $param")
}
}
用法:
MySingleton.getInstance("something").printParam()
如果您正在寻找具有多个参数的基本SingletonHolder类。我创建了SingletonHolder泛型类,它只支持创建一个带有一个参数、两个参数和三个参数的singleton类实例 非参数(Kotlin的默认值):
object AppRepository
class AppRepository private constructor(private val db: Database) {
companion object : SingleArgSingletonHolder<AppRepository, Database>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db)
class AppRepository private constructor(private val db: Database, private val apiService: ApiService) {
companion object : PairArgsSingletonHolder<AppRepository, Database, ApiService>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db, apiService)
class AppRepository private constructor(
private val db: Database,
private val apiService: ApiService,
private val storage : Storage
) {
companion object : TripleArgsSingletonHolder<AppRepository, Database, ApiService, Storage>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db, apiService, storage)
一个参数(来自上面链接中的示例代码):
object AppRepository
class AppRepository private constructor(private val db: Database) {
companion object : SingleArgSingletonHolder<AppRepository, Database>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db)
class AppRepository private constructor(private val db: Database, private val apiService: ApiService) {
companion object : PairArgsSingletonHolder<AppRepository, Database, ApiService>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db, apiService)
class AppRepository private constructor(
private val db: Database,
private val apiService: ApiService,
private val storage : Storage
) {
companion object : TripleArgsSingletonHolder<AppRepository, Database, ApiService, Storage>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db, apiService, storage)
class AppRepository私有构造函数(private val db:Database){
伴生对象:SingleArgSingletonHolder(::AppRepository)
}
//使用
val appRepository=appRepository.getInstance(db)
两个参数:
object AppRepository
class AppRepository private constructor(private val db: Database) {
companion object : SingleArgSingletonHolder<AppRepository, Database>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db)
class AppRepository private constructor(private val db: Database, private val apiService: ApiService) {
companion object : PairArgsSingletonHolder<AppRepository, Database, ApiService>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db, apiService)
class AppRepository private constructor(
private val db: Database,
private val apiService: ApiService,
private val storage : Storage
) {
companion object : TripleArgsSingletonHolder<AppRepository, Database, ApiService, Storage>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db, apiService, storage)
class AppRepository私有构造函数(私有val db:数据库,私有val apiService:apiService){
伴生对象:PairArgSingleTonHolder(::AppRepository)
}
//使用
val appRepository=appRepository.getInstance(db,apiService)
三个参数:
object AppRepository
class AppRepository private constructor(private val db: Database) {
companion object : SingleArgSingletonHolder<AppRepository, Database>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db)
class AppRepository private constructor(private val db: Database, private val apiService: ApiService) {
companion object : PairArgsSingletonHolder<AppRepository, Database, ApiService>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db, apiService)
class AppRepository private constructor(
private val db: Database,
private val apiService: ApiService,
private val storage : Storage
) {
companion object : TripleArgsSingletonHolder<AppRepository, Database, ApiService, Storage>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db, apiService, storage)
class AppRepository私有构造函数(
私有val数据库:,
私人增值服务:增值服务,
专用val存储:存储
) {
伴生对象:三耳单音持有人(::AppRepository)
}
//使用
val appRepository=appRepository.getInstance(数据库、apiService、存储)
超过3个参数:
object AppRepository
class AppRepository private constructor(private val db: Database) {
companion object : SingleArgSingletonHolder<AppRepository, Database>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db)
class AppRepository private constructor(private val db: Database, private val apiService: ApiService) {
companion object : PairArgsSingletonHolder<AppRepository, Database, ApiService>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db, apiService)
class AppRepository private constructor(
private val db: Database,
private val apiService: ApiService,
private val storage : Storage
) {
companion object : TripleArgsSingletonHolder<AppRepository, Database, ApiService, Storage>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db, apiService, storage)
为了实现这种情况,我建议创建一个config对象来传递给singleton构造函数。这与Jeremy的解决方案相同,但语法不同。单例仍然是在没有任何参数的情况下创建的。如果希望它像构造函数一样工作,只需返回
this
。我已经更新了答案,证明了这一点。好吧,但是什么阻止你在不调用invoke
方法的情况下使用对象呢?这个答案有几个大缺点。首先,调用方可能忘记调用init
。第二个是参数存储在var
中,这意味着以后可能会错误地更改它,通常在单例中,您不希望以后修改构造期间所需的内容。第三,这个答案甚至没有使用方法链接,这让使用起来很痛苦。这个答案不是这个问题的最佳实践,正如@Sature9Nine所说,这很好,但使用对象的主要原因是要消除这个同步的单例创建代码。不,此示例不正确,因为您仍然可以在初始化之前调用Singleton.SaveData()
。您还可以随时更改注入的参数,这不是单例所能做到的——除非特别需要。