Синглтон с аргументом в Котлине

Ссылка Kotlin говорит, что я могу создать синглтон, используя ключевое слово object следующим образом:

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

Тем не менее, я хотел бы передать аргумент этому объекту. Например, ApplicationContext в проекте Android.

Есть ли способ сделать это?

6 ответов

Решение

Поскольку объекты не имеют конструкторов, я сделал следующее, чтобы ввести значения при начальной настройке. Вы можете вызывать функцию как хотите, и ее можно вызывать в любое время, чтобы изменить значение (или восстановить синглтон в зависимости от ваших потребностей).

object Singleton {
    private var myData: String = ""

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

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

Kotlin имеет функцию, называемую перегрузкой оператора, которая позволяет передавать аргументы непосредственно объекту.

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

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

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

С большинством существующих ответов можно получить доступ к членам класса без предварительной инициализации синглтона. Вот пример безопасного потока, который гарантирует, что один экземпляр создается перед доступом к любому из его членов.

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()

Есть также две нативные библиотеки инъекций Kotlin, которые довольно просты в использовании и имеют другие формы синглетонов, включая потоки, ключи и т. Д. Не уверен, если это в контексте вашего вопроса, но вот ссылки на оба:

Обычно в Android люди используют такую ​​библиотеку или Dagger и др. Для параметризации синглетонов, определения их объема и т. Д.

Я рекомендую вам использовать эту форму для передачи аргументов в siglot в kotlin debit о том, что объект, который ваш конструктор лишен и заблокирован:

object Singleton {

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

fun SaveData() {}

}

и вы называете это так в деятельности

Singleton.instance(this).SaveData()

Если вы ищете базовый класс SingletonHolder с более чем одним аргументом. Я создал универсальный класс SingletonHolder, который поддерживает создание только одного экземпляра класса singleton с одним аргументом, двумя аргументами и тремя аргументами.

ссылка Github базового класса здесь

Без аргументов (по умолчанию 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)

Более 3-х аргументов:

Чтобы реализовать этот случай, я предлагаю создать объект конфигурации для передачи конструктору синглтона.

Другие вопросы по тегам