ViewModel and LiveData extensions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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