当 Jetpack Compose 中的指定流程发生更改时,如何启动重组?

Hel*_*oCW 2 kotlin android-jetpack-compose compose-recomposition

我知道Column(){...}b1orb2改变时,将会重新组合。

如果我希望只有改变的Column(){...}时候才可以重新组合,而改变的 时候不重新组合,怎么办?b2Column(){...}b1

@Composable
fun ScreenDetail(
    mViewMode: SoundViewModel
) {
      val b1=mViewMode.a1.collectAsState(initial = 0)
      val b2=mViewMode.a2.collectAsState(initial = 0)
      
      Column() {
          Text(" ${b1.value}   ${b2.value}")

          Text(Calendar.getInstance().time.toSeconds())
      }
}

fun Date.toSeconds():String{
    return SimpleDateFormat("yyyy/MM/dd HH:mm:ss", Locale.US).format(this)
}

class SoundViewModel(): ViewModel() {
    var i = 0
    val a1: Flow<Int> = flow {
        while (true) {
            emit(i++)
            delay(1000)
        }
    }

    val a2: Flow<Int> = flow {
        while (true) {
            emit(i)
            delay(2000)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Thr*_*ian 6

如果需要进行作用域重组,则需要创建作用域。我所说的范围是指创建一个与列、行或框不同的非内联可组合项。您可以在此链接中查看答案和文章。

Compose 重组读取状态的最接近的范围/函数。如果你读过

   Text(" ${b1.value}   ${b2.value}")
Run Code Online (Sandbox Code Playgroud)

当任何这些状态发生变化时,您的列将被重组。但如上所述,即使您阅读了其中的任何内容,它们也应该已更改,因为 Column 不会创建范围

@Composable
fun ScreenDetail2(
    mViewMode: SoundViewModel
) {
    val b1=mViewMode.a1.collectAsState(initial = 0)
    val b2=mViewMode.a2.collectAsState(initial = 0)

    Column(modifier= Modifier.background(getRandomColor()).fillMaxWidth()) {
        Text("${b1.value}")

    }

    Column(modifier= Modifier.background(getRandomColor()).fillMaxWidth()) {
       Text("${b2.value}")
   }
}
Run Code Online (Sandbox Code Playgroud)

但是如果你创建一个函数,例如

@Composable
private fun MyColumn(counter:Int){
    Column(modifier= Modifier.background(getRandomColor()).fillMaxWidth()) {
        Text("$counter")
    }
}
Run Code Online (Sandbox Code Playgroud)

您将拥有您读取的每个值的范围

@Composable
fun ScreenDetail3(
    mViewMode: SoundViewModel
) {
    val b1=mViewMode.a1.collectAsState(initial = 0)
    val b2=mViewMode.a2.collectAsState(initial = 0)

    MyColumn(b1.value)
    MyColumn(b2.value)
}
Run Code Online (Sandbox Code Playgroud)

正如您在 gif 中看到的,当 b1 或 b2 更改时,ScreenDetail2 会重新组合每个列,但 ScreenDetail3 只会重新组合各自的功能范围。我将 b1 的延迟时间更改为 300,将 b2 的延迟时间更改为 2000,以使重组易于视觉观察。

顶部 2 列来自ScreenDetail2,底部来自ScreenDetail3

在此输入图像描述

重组可以通过多种方式观察,我补充2

类 Ref(var 值:Int)

// Note the inline function below which ensures that this function is essentially
// copied at the call site to ensure that its logging only recompositions from the
// original call site.
@Composable
inline fun LogCompositions(msg: String) {
    val ref = remember { Ref(0) }
    SideEffect { ref.value++ }
    println("$msg, recomposition: ${ref.value}")
}
Run Code Online (Sandbox Code Playgroud)

或改变颜色

fun getRandomColor() =  Color(
    red = Random.nextInt(256),
    green = Random.nextInt(256),
    blue = Random.nextInt(256),
    alpha = 255
)
Run Code Online (Sandbox Code Playgroud)