Skip to content

Instantly share code, notes, and snippets.

@Swisyn
Forked from osipxd/EventsQueue.kt
Created May 13, 2020 11:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Swisyn/d36b5c262708b3ccd0be9be5879e23dc to your computer and use it in GitHub Desktop.
Save Swisyn/d36b5c262708b3ccd0be9be5879e23dc to your computer and use it in GitHub Desktop.
ViewModel and LiveData extensions
import androidx.annotation.MainThread
import androidx.lifecycle.MutableLiveData
import java.util.LinkedList
import java.util.Queue
/**
* Класс-очередь для обработки временных событий, не являющихся частью View
* Например, показ SnackBar с сообщением или ошибкой.
*/
class EventsQueue : MutableLiveData<Queue<Event>>() {
@MainThread
fun offer(event: Event) {
val queue = (value ?: LinkedList()).apply {
add(event)
}
value = queue
}
}
/**
* Подписка на [LiveData] с очередью одноразовых событий (например, показы снэкбаров и диалогов).
* @see EventsQueue
*/
fun Fragment.observe(eventsQueue: EventsQueue, eventHandler: (Event) -> Unit) {
eventsQueue.observe(viewLifecycleOwner) { queue: Queue<Event>? ->
while (queue != null && queue.isNotEmpty()) {
eventHandler(queue.remove())
}
}
}
import androidx.fragment.app.Fragment
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.observe
fun <T> MutableLiveData<T>.onNext(next: T) {
this.value = next
}
fun <T : Any> LiveData<T>.requireValue(): T = checkNotNull(value)
/**
* Подписка на [LiveData].
*
* Пример подписки на изменения состояния:
* ```
* lateinit var viewModel: MyViewModel
*
* override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
* super.onViewCreated(view, savedInstanceState)
* observe(viewModel.state, ::renderState)
* }
* ```
*/
inline fun <reified T, LD : LiveData<T>> Fragment.observe(liveData: LD, crossinline block: (T) -> Unit) {
liveData.observe(viewLifecycleOwner) { block(it) }
}
import androidx.lifecycle.MutableLiveData
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/**
* Делегат для работы с содержимым [MutableLiveData] как с полем.
*
* Без делегата пришлось бы писать такой код:
* ```
* val liveState = MutableLiveData<IntroViewState>(initialState)
* var state: IntroViewState
* get() = liveState.requireValue()
* set(value) = liveState.onNext(value)
* ```
* С делегатом для такой же логики достаточно написать:
* ```
* val liveState = MutableLiveData<IntroViewState>(initialState)
* var state: IntroViewState by liveState.delegate()
* ```
*/
fun <T : Any> MutableLiveData<T>.delegate(): ReadWriteProperty<Any, T> {
return object : ReadWriteProperty<Any, T> {
override fun setValue(thisRef: Any, property: KProperty<*>, value: T) = onNext(value)
override fun getValue(thisRef: Any, property: KProperty<*>): T = requireValue()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment