Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 350 Vote(s) - 3.65 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Singleton with argument in Kotlin

#1
The [Kotlin reference][1] says that I can create a singleton using the *object* keyword like so:

object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
//
}
}

However, I would like to pass an argument to that object. For example an ApplicationContext in an Android project.

Is there a way to do this?

[1]:

[To see links please register here]

Reply

#2
Since objects do not have constructors what I have done the following to inject the values on an initial setup. You can call the function whatever you want and it can be called at any time to modify the value (or reconstruct the singleton based on your needs).

object Singleton {
private var myData: String = ""

fun init(data: String) {
myData = data
}

fun singletonDemo() {
System.out.println("Singleton Data: ${myData}")
}
}
Reply

#3
There are also two native Kotlin injection libraries that are quite easy to use, and have other forms of singletons including per thread, key based, etc. Not sure if is in context of your question, but here are links to both:

* Injekt (mine, I'm the author):

[To see links please register here]

* Kodein (similar to Injekt):

[To see links please register here]


Typically in Android people are using a library like this, or Dagger, et al to accomplish parameterizing singletons, scoping them, etc.

Reply

#4
Kotlin has a feature called [Operator overloading][1], letting you pass arguments directly to an object.

<!-- language: kotlin -->

object DataProviderManager {
fun registerDataProvider(provider: String) {
//
}

operator fun invoke(context: ApplicationContext): DataProviderManager {
//...
return this
}
}

//...
val myManager: DataProviderManager = DataProviderManager(someContext)

[1]:

[To see links please register here]

Reply

#5
I recommend that you use this form to pass arguments in a singleton in Kotlin debit that the object your constructor is deprived and blocked:

object Singleton {

fun instance(context: Context): Singleton {
return this
}

fun SaveData() {}
}

and you call it this way in the activity

Singleton.instance(this).SaveData()
Reply

#6
With most of the existing answers it's possible to access the class members without having initialized the singleton first. Here's a thread-safe sample that **ensures** that a single instance is created before accessing any of its members.

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")
}
}

Usage:

MySingleton.getInstance("something").printParam()

Reply

#7
If you looking for a base SingletonHolder class with more than one argument. I had created the SingletonHolder generic class, which supports to create only one instance of the singleton class with one argument, two arguments, and three arguments.

[link Github of the base class here][1]

**Non-argument (default of Kotlin):**

object AppRepository

**One argument (from an example code in the above link):**

class AppRepository private constructor(private val db: Database) {
companion object : SingleArgSingletonHolder<AppRepository, Database>(::AppRepository)
}
// Use
val appRepository = AppRepository.getInstance(db)

**Two arguments:**

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)

**Three arguments:**

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)

**More than 3 arguments:**

To implement this case, I suggest creating a config object to pass to the singleton constructor.

[1]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through