Intereting Posts
Ошибка decimalFormat.format () Настройка прослушивателей Android в Kotlin – использование возврата в lambdas проекции не допускаются для непосредственных подтипов супертипа Kotlin "Любой тип, который реализует интерфейс" Kotlin: отображение неизменяемого списка в API Обратный звонок TableView в Котлине Отображение, если исключение Как правильно реализовать lateinit с пользовательскими объектами класса для использования в onCreate () в android, избегая ошибки Property getter или setter expected Codename. Ошибки сборки, связанные с Kotlin Выступления в конструкторе Котлин Ошибка при создании Enum в качестве первичного ключа в библиотеке базы данных Room Intellij IDEA не показывает доступные предложения для ресурсов Android в файлах Kotlin Почему я могу вставить код строки до DayForecast (HashMap (it)) в Котлин? Перехват события касания и перенаправление его в зависимости от состояния события движения Kotlin lazy свойство в зависимости от другого свойства, инициализированного в init

Больше удовольствия с делегатами Котлина

Если вы знакомы с экспериментальными компонентами архитектуры Android Android, вы, вероятно, знаете MutableLiveData . Пытаясь сделать это немного интереснее, я пришел с:

 class KotlinLiveData<T>(val default: T) { val data = MutableLiveData<T>() operator fun getValue(thisRef: Any?, property: KProperty<*>):T { return data.value ?: default } operator fun setValue(thisRef: Any?, property: KProperty<*>, value:T) { if (Looper.myLooper() == Looper.getMainLooper()) { data.value = value } else { data.postValue(value) } } } 

И тогда я могу:

 var name : String by KotlinLiveData("not given") name = "Chrzęszczybrzęczykiewicz" 

Но, увы – это делает data которые необходимы, чтобы регистрировать Observer недоступным:

 name.data.observe(this, nameObserver) // won't work :( 

Любая идея, если я смогу это получить?

Solutions Collecting From Web of "Больше удовольствия с делегатами Котлина"

Вы можете получить доступ к объекту delegate этого свойства и получить от него MutableLiveData<T> :

 inline fun <reified R> KProperty<*>.delegateAs<R>(): R? { isAccessible = true return getDelegate() as? R } 

Тогда использование:

 ::name.delegateAs<KotlinLiveData<String>>?.data?.observe(this, nameObserver) 

Чтобы ссылаться на свойство member, используйте this::name или someInstance::name .

Это решение требует, чтобы вы добавляли API отражения Kotlin, kotlin-reflect , в зависимости от вашего проекта. Кроме того, из-за стирания типа .delegateAs<KotlinLiveData<String>> не является безопасным для типа: он может только проверить, что делегат – это KotlinLiveData<*> но не тот, что его аргумент типа является String .

самый простой способ, которым вы можете добиться, – сделать делегат в поле, например:

 @JvmField val dataOfName = KotlinLiveData("not given") var name : String by dataOfName 

то вы можете использовать живые данные в классе, например:

 dataOfName.data.observe(this, nameObserver) name = "Chrzęszczybrzęczykiewicz" 

ИЛИ вы можете написать синтаксис suglar, например:

 var name : String by live("not given").observe(this, nameObserver) 

Обратите внимание, что вы также можете сделать nameObserver , например:

 val observers by lazy{mutableListOf<Observer>()} var name : String by live("not given").observe(this){data-> observers.forEach{it.dataChanged(data)} } 

то вы можете сделать что-то вроде ниже:

 observers+= nameObserver; name = "Chrzęszczybrzęczykiewicz" observers-= nameObserver; 

Благодаря решению hotkey, вот какой код лучше:

 class KotlinLiveData<T>(val default: T, val liveData : MutableLiveData<T>? = null) { val data = liveData ?: MutableLiveData<T>() operator fun getValue(thisRef: Any?, property: KProperty<*>):T { return data.value ?: default } operator fun setValue(thisRef: Any?, property: KProperty<*>, value:T) { if (Looper.myLooper() == Looper.getMainLooper()) { data.value = value } else { data.postValue(value) } } } inline fun <reified R> KMutableProperty0<*>.getLiveData(): MutableLiveData<R> { isAccessible = true return (getDelegate() as KotlinLiveData<R>).data } inline fun <reified R> KMutableProperty0<*>.observe(owner: LifecycleOwner, obs : Observer<R>) { isAccessible = true (getDelegate() as KotlinLiveData<R>).data.observe(owner,obs) } 

Теперь я могу:

someViewModel::name.observe(myActivity, Observer<String>{...})

с

someViewModel.name = "Kowalski, Leon"

работая как ожидалось

Этот класс позволяет использовать LiveData с Android Data Binding из коробки.