在 Kotlin 中有参数的单例
Singleton with argument in Kotlin
Kotlin reference 说我可以使用 object 关键字创建单例,如下所示:
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
//
}
}
但是,我想向该对象传递一个参数。例如 Android 项目中的 ApplicationContext。
有办法吗?
由于对象没有构造函数,因此我执行了以下操作以在初始设置中注入值。您可以随意调用该函数,并且可以随时调用它来修改值(或根据您的需要重建单例)。
object Singleton {
private var myData: String = ""
fun init(data: String) {
myData = data
}
fun singletonDemo() {
System.out.println("Singleton Data: ${myData}")
}
}
还有两个非常易于使用的本机 Kotlin 注入库,并且具有其他形式的单例,包括每线程、基于键等。不确定是否在您的问题上下文中,但这里有指向的链接两者:
- Injekt(我的,我是作者):https://github.com/kohesive/injekt
- Kodein(类似于 Injekt):https://github.com/SalomonBrys/Kodein
通常在 Android 中,人们使用这样的库或 Dagger 等来完成单例参数化、范围界定等。
Kotlin 有一个名为 Operator overloading 的功能,让您可以将参数直接传递给对象。
object DataProviderManager {
fun registerDataProvider(provider: String) {
//
}
operator fun invoke(context: ApplicationContext): DataProviderManager {
//...
return this
}
}
//...
val myManager: DataProviderManager = DataProviderManager(someContext)
我建议您使用这种形式在 Kotlin 的单例中传递参数,借记您的构造函数被剥夺和阻止的对象:
object Singleton {
fun instance(context: Context): Singleton {
return this
}
fun SaveData() {}
}
你在 activity
中这样称呼它
Singleton.instance(this).SaveData()
对于大多数现有答案,无需先初始化单例就可以访问 class 成员。这是一个线程安全示例,它确保在访问其任何成员之前创建单个实例。
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 class。我已经创建了 SingletonHolder 泛型 class,它支持仅创建一个单例实例 class,具有一个参数、两个参数和三个参数。
link Github of the base class here
非参数(Kotlin 的默认值):
object AppRepository
一个参数(来自上面link中的示例代码):
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)
超过 3 个参数:
为了实现这种情况,我建议创建一个配置对象以传递给单例构造函数。
Kotlin reference 说我可以使用 object 关键字创建单例,如下所示:
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
//
}
}
但是,我想向该对象传递一个参数。例如 Android 项目中的 ApplicationContext。
有办法吗?
由于对象没有构造函数,因此我执行了以下操作以在初始设置中注入值。您可以随意调用该函数,并且可以随时调用它来修改值(或根据您的需要重建单例)。
object Singleton {
private var myData: String = ""
fun init(data: String) {
myData = data
}
fun singletonDemo() {
System.out.println("Singleton Data: ${myData}")
}
}
还有两个非常易于使用的本机 Kotlin 注入库,并且具有其他形式的单例,包括每线程、基于键等。不确定是否在您的问题上下文中,但这里有指向的链接两者:
- Injekt(我的,我是作者):https://github.com/kohesive/injekt
- Kodein(类似于 Injekt):https://github.com/SalomonBrys/Kodein
通常在 Android 中,人们使用这样的库或 Dagger 等来完成单例参数化、范围界定等。
Kotlin 有一个名为 Operator overloading 的功能,让您可以将参数直接传递给对象。
object DataProviderManager {
fun registerDataProvider(provider: String) {
//
}
operator fun invoke(context: ApplicationContext): DataProviderManager {
//...
return this
}
}
//...
val myManager: DataProviderManager = DataProviderManager(someContext)
我建议您使用这种形式在 Kotlin 的单例中传递参数,借记您的构造函数被剥夺和阻止的对象:
object Singleton {
fun instance(context: Context): Singleton {
return this
}
fun SaveData() {}
}
你在 activity
中这样称呼它Singleton.instance(this).SaveData()
对于大多数现有答案,无需先初始化单例就可以访问 class 成员。这是一个线程安全示例,它确保在访问其任何成员之前创建单个实例。
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 class。我已经创建了 SingletonHolder 泛型 class,它支持仅创建一个单例实例 class,具有一个参数、两个参数和三个参数。
link Github of the base class here
非参数(Kotlin 的默认值):
object AppRepository
一个参数(来自上面link中的示例代码):
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)
超过 3 个参数:
为了实现这种情况,我建议创建一个配置对象以传递给单例构造函数。