Android全新UI框架之Compose状态管理与重组

Compose采取了声明式UI的开发范式。在这种范式中,UI的职责仅作为数据状态的反应。如果数据状态没有变化,则UI永远不会自行改变。如果把Composable的执行看作是一个函数运算,那么状态就是函数的参数,生成的布局就是函数的输出。

Stateless和Stateful

传统视图中通过获取组件对象句柄来更新组件状态,而Compose则通过重新执行Composable函数来更新页面(重组)。StatelessComposable只依赖参数的Composable;相对的,有些Composable内部持有或者访问了某些状态,称之为StatefulComposable。StatelessComposable的重组只能来自上层Composable的调用,而StatefulComposable的重组来自其以来的状态的变化。

//Statelesscomposable
@Composable
fun  Hello(name:String){
   
    Text(text = "Hello $name")
}

//StatefulComposable
@Preview
@Composable
fun CounterComponent() {
   

    Column(
        modifier = Modifier.padding(16.dp)
    ) {
   
    //remember中计算得到的数据会自动缓存,当Composable重组再次执行到remember处会返回之前已缓存的数据,无须重新计算。mutableStateOf的调用一定要出现在remember中,不然每次重组都会创建新的状态。
        var counter by remember {
    mutableStateOf(0) }

        Text( //1
            "Click the buttons to adjust your value:",
            Modifier.fillMaxWidth(),
            textAlign = TextAlign.Center
        )

        Text( //2
            "$counter",
            Modifier.fillMaxWidth(),
            textAlign = TextAlign.Center,
            style = typography.h3
        )

        Row {
   
            Button(
                onClick = {
    counter-- },
                Modifier.weight(1f)
            ) {
   
                Text("-")
            }
            Spacer(Modifier.width(16.dp))
            Button(
                onClick = {
    counter++ },
                Modifier.weight(1f)
            ) {
   
                Text("+")
            }
        }
    }
}

在Compose中使用State<T>描述一个状态,泛型T是状态的具体类型。

interface State<out T> {
   
    val value: T
}

State<T>是一个可观察对象。当Composabel对State的value进行读取时会与State建立订阅关系,当value发生变化时,作为监听者的Composable会自动重组刷新UI。
有时候Composable需要对State的value进行修改,比如在CounterComponent中单击按钮需要修改counter的值,所以counter可被修改,使用MutableState<T>来表示可修改状态,其包裹的数据是一个可修改的var类型。

@Stable
interface MutableState<T> : State<T> {
   
    override var value: T
    operator fun component1(): T
    operator fun component2(): (T) -> Unit
}

MutableState有三种用法:

  1. 创建MutableState

     var counter:MutableState<Int> = mutableStateOf(0)
    
  2. 解构方式

      val(counter,setCounter) = mutableStateOf(0)
    

    此时的counter已经是一个Int类型的数据,后续使用的地方可以直接访问,无须再使用点操作符获取value,而需要更新counter的地方可以使用setCounter(xx)完成。

  3. 属性代理
    使用by关键字直接获取Int类型counter。

    var counter by mutableStateOf(0) 
    

    by关键字的原理是对counter的读写会通过getValue和setValue这两个运算符的重写最终代理为对value的操作。

状态上提

状态上提的通常做法是将内部状态移除,通过参数传入需要在UI显示的状态,以及需要回调给调用方的事件,案例如下所示:

@Composable
fun CounterComponent(
    counter:Int,//重组时调用方传入当前需要显示的计数
    onIncrement:()->Unit,//向调用方回调单击加号的事件
    onDecrement:()->Unit,//向调用方回调单击减号的事件
) {
   

    Column(
        modifier = Modifier.padding(16.dp)
    ) {
   
        Text( //1
            "Click the buttons to adjust your value:",
            Modifier.fillMaxWidth(),
            textAlign = TextAlign.Center
        )

        Text( //2
            "$counter",
            Modifier.fillMaxWidth(),
            tex
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值