Sobes.tech
Middle

K čemu slouží StateFlow v vývoji Androidu?

sobes.tech AI

Odpověď od AI

StateFlow se používá k reprezentaci měnitelného, horkého toku hodnot, který má vždy počáteční hodnotu a reprodukuje poslední emitovanou hodnotu pro nové odběratele.

Hlavní případy použití:

  1. Uložení stavu UI: Často se používá v ViewModelu k ukládání a správě stavu, který je zobrazen na UI. Activity/Fragment se přihlašují k StateFlow a reagují na změny stavu.
  2. Nahrazení LiveData: V mnoha případech může nahradit LiveData, zejména v projektech využívajících Kotlin Coroutines a Flow. StateFlow poskytuje flexibilnější možnosti zpracování dat pomocí operátorů Flow.
  3. Výměna dat mezi komponentami: Umožňuje bezpečně vyměňovat data mezi různými částmi aplikace, zajišťujíc, že odběratelé vždy obdrží aktuální stav.

Výhody StateFlow:

  • Horký tok: Aktivní bez ohledu na přítomnost odběratelů, vždy udržuje poslední hodnotu.
  • Počáteční hodnota: Vždy má počáteční hodnotu, což je vhodné pro reprezentaci aktuálního stavu.
  • Sloučení identických hodnot: Ve výchozím nastavení nevysílá sekvenční identické hodnoty, což může optimalizovat práci UI.
  • Interoperabilita s Flow: Snadno se integruje s jinými operátory Flow pro transformaci a zpracování dat.

Příklad použití v ViewModelu:

// ViewModel
class MyViewModel : ViewModel() {

    private val _uiState = MutableStateFlow(UiState.Loading) // MutableStateFlow pro změnu
    val uiState: StateFlow<UiState> = _uiState.asStateFlow() // StateFlow pro přístup zvenčí

    init {
        // Inicializace nebo načítání dat
        viewModelScope.launch {
            // ... načítání dat
            _uiState.value = UiState.Content("Hello, StateFlow!")
        }
    }

    sealed class UiState {
        object Loading : UiState()
        data class Content(val text: String) : UiState()
        data class Error(val message: String) : UiState()
    }
}

// Activity/Fragment
class MyFragment : Fragment() {

    private val viewModel: MyViewModel by viewModels()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        viewLifecycleOwner.lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.uiState.collect { state ->
                    when (state) {
                        MyViewModel.UiState.Loading -> showLoading()
                        is MyViewModel.UiState.Content -> showContent(state.text)
                        is MyViewModel.UiState.Error -> showError(state.message)
                    }
                }
            }
        }
    }
}