Однонаправленный поток данных

Последнее обновление: 04.04.2024

Однонаправленный поток данных (unidirectional data flow) представляет подход, при котором состояние компонента не может напрямую изменяться дочерними, вложенными компонентами. Применение однонаправленного потока данных упрощает создание модульных, независимых друг от друга компонентов и, как следствие, упрощает разработку приложения и его тестирование. Например, возьмем следующий пример:

package com.example.helloapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Counter()
        }
    }
}
@Composable
fun Counter(){
    val clicksState = remember{mutableStateOf(0)}
    val onClicksChange = { value : Int ->
        clicksState.value = value
    }
    Column{
        Text(text = "Clicks: ${clicksState.value}", fontSize = 28.sp )
        Increment(clicksState.value, onClicksChange)
    }

}
@Composable
fun Increment(clicks: Int, onClicksChange : (Int) -> Unit){
    Text(
        text = "+",
        fontSize = 36.sp,
        modifier = Modifier.clickable( onClick = {onClicksChange(clicks+1)})
            .border(1.dp, Color.DarkGray)
            .padding(10.dp, 0.dp)
    )
}

Здесь у нас есть компонент Counter. Этот компонент определяет состояние clicksState, которое хранит количество нажатий, и функицю onClicksChange, которая изменяет это состояние:

val clicksState = remember{mutableStateOf(0)}
val onClicksChange = { value : Int ->
    clicksState.value = value
}

onClicksChange представлет функцию, которая принимает один параметр типа Int - новое значение и передает его в состояние clicksState.

Внутри Counter для вывода состояния и его изменения определены два компонента:

Column{
    Text(text = "Clicks: ${clicksState.value}", fontSize = 28.sp )
    Increment(clicksState.value, onClicksChange)
}

Первый компонент - Text просто выводит текущее состояние на экран устройства.

Второй компонент - Increment призван изменять значение состояния. В него как раз передаются текущее значение состояния и функция изменения состояния. Посмотрим на его определение:

@Composable
fun Increment(clicks: Int, onClicksChange : (Int) -> Unit){
    Text(
        text = "+",
        fontSize = 36.sp,
        modifier = Modifier.clickable( onClick = {onClicksChange(clicks+1)})
            .border(1.dp, Color.DarkGray)
            .padding(10.dp, 0.dp)
    )
}

Данный компонент в качестве параметров принимает текущее количество нажатий (по сути текущее значение состояния) и функцию для изменения. Внутри этого компонента также определен компонент Text с примитивной стилизацией под кнопку увеличения. По нажатию на этот компонент будет вызываться переданная функция onClicksChange(), в которую передается новое значение нажатий.

Таким образом, при нажатии на компонент Increment произойдет вызов функции onClicksChange и изменение состояния"

Unidirectional data flow в приложении на Jetpack Compose на Kotlin на Android

Таким образом, мы можем отдельно развивать компоненты Counter и Increment. При этом, хотя и Increment вызывает изменение состояния, но реальное изменение - определение функции onClicksChange все равно происходит в Counter. Increment напрямую не изменяет состояние компонента Counter.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850