Kotlin reference表示我可以使用 object 关键字创建单例,如下所示:
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
//
}
}
但是,我想将一个参数传递给该对象。例如,Android项目中的ApplicationContext。
有办法做到这一点吗?
答案 0 :(得分:14)
由于对象没有构造函数,因此我在以下步骤中将值注入初始设置。你可以随意调用函数,可以随时调用它来修改值(或根据你的需要重建单例)。
object Singleton {
private var myData: String = ""
fun init(data: String) {
myData = data
}
fun singletonDemo() {
System.out.println("Singleton Data: ${myData}")
}
}
答案 1 :(得分:4)
Kotlin有一个名为Operator overloading的功能,允许您将参数直接传递给对象。
object DataProviderManager {
fun registerDataProvider(provider: String) {
//
}
operator fun invoke(context: ApplicationContext): DataProviderManager {
//...
return this
}
}
//...
val myManager: DataProviderManager = DataProviderManager(someContext)
答案 2 :(得分:2)
还有两个本机Kotlin注入库非常容易使用,并且有其他形式的单例,包括每个线程,基于密钥等。不确定是否在您的问题的上下文中,但这里是两者的链接:
通常在Android中,人们使用像这样的库,或者Dagger等人来完成单例参数化,范围化等等。
答案 3 :(得分:1)
我建议您使用这种形式在Kotlin的Siglot中传递参数,以借记您的构造函数的对象被剥夺并被阻止:
object Singleton {
fun instance(context: Context): Singleton {
return this
}
fun SaveData() {}
}
您在活动中这样称呼
Singleton.instance(this).SaveData()
答案 4 :(得分:1)
使用大多数现有答案,就可以访问类成员而无需先初始化单例。这是一个线程安全的示例,可以确保在访问其任何成员之前创建一个实例。
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()
答案 5 :(得分:0)
如果您正在寻找具有多个参数的基本 SingletonHolder 类。我创建了 SingletonHolder 泛型类,该类支持仅创建带有一个参数、两个参数和三个参数的单例类的一个实例。
link Github of the base class here
非参数(Kotlin 的默认设置):
def network_fn(obs):
f_output = 128
g_output = 128
node_embeddings = obs
# layer g
G = tf.keras.layers.Dense(units=g_output,
use_bias=True,
kernel_initializer=ortho_init(np.sqrt(2)),
bias_initializer=tf.constant_initializer(0.0),
activation=None,
name="g")
# layer f
f = tf.keras.layers.Dense(units=f_output,
use_bias=True,
kernel_initializer=ortho_init(np.sqrt(2)),
bias_initializer=tf.constant_initializer(0.0),
activation=None,
name="f_%i" % edge_type_idx))
f_output = f(node_embeddings)
f_output = tf.nn.tanh(f_output)
G_input = tf.concat([node_embeddings, f_output], axis=-1)
G_output = G(G_input)
G_output = tf.nn.tanh(G_output)
return G_output
一个参数(来自上面链接中的示例代码):
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)
超过 3 个参数:
为了实现这种情况,我建议创建一个配置对象来传递给单例构造函数。