StateFlow, End of LiveData? — статья о StateFlow, новом классе библиотеки короутин Kotlin (начиная с 1.3.6) для хранения состояний.
Другие статьи на тему Kotlin:
- Основы функционального программирования на Kotlin
- Перегрузка операторов в Kotlin
- Введение в Kotlin Flow
Сразу начнем с примера:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
fun main() = runBlocking { val stateFlow = MutableStateFlow<Int>(0) // Следим за изменением состояния val job = launch { stateFlow.collect { print("$it ") } } // Изменяем состояние (1..5).forEach { delay(500) stateFlow.value = it } job.cancel() job.join() } |
StateFlow базируется на потоках и позволяет разным компонентам приложения менять состояние и реагировать на изменение этого состояния.
В Android StateFlow можно использовать в качестве более продвинутого аналога LiveData. Создадим, например, следующую ViewModel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@ExperimentalCoroutinesApi class MainViewModel : ViewModel() { private val _countState = MutableStateFlow(0) val countState: StateFlow<Int> = _countState fun incrementCount() { _countState.value++ } fun decrementCount() { _countState.value-- } } |
Теперь создадим активность, использующую эту модель. Активность будет состоять из TextView, показывающего число, и двух кнопок для увеличения и уменьшения этого числа:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
class MainActivity : AppCompatActivity() { private val viewModel by lazy { ViewModelProvider(this)[MainViewModel::class.java] } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) initCountObserver() initView() } } private fun initCountObserver() { lifecycleScope.launch { viewModel.countState.collect { value -> textview_count.text = "$value" } } } private fun initView() { button_plus.setOnClickListener(::incrementCounter) button_minus.setOnClickListener(::decrementCounter) } private fun incrementCounter(view: View) { viewModel.incrementCount() } private fun decrementCounter(view: View) { viewModel.decrementCount() } |
Это все. Нажатие кнопки изменения числа изменит состояние ViewModel, а это, в свою очередь, приведет к автоматическому изменению TextView. И все это работает с учетом жизненного цикла активности благодаря использованию lifecycleScope.