在我找到的示例(herehere)中,我看到derivedStateOf总是包装在remember块中.判断重新组合的计数,我看不出有什么区别

val foo = remember { derivedStateOf { someState } }

val foo = derivedStateOf { someState }

谁能给我举一个结果不同的例子?

编辑: 所以我在这个例子中得到了一个不同的结果:

@Composable
fun Test() {
    var count by remember {
        mutableStateOf(0)
    }

    val moreThanOne = derivedStateOf {
        Log.d("foo", "Calculate")
        count > 1
    }

    Log.d("foo", "Read")
    moreThanOne.value

    Button(
        onClick = {
            Log.d("foo", "Clicked")
            count += 1
        }
    ) {
        Text(text = "Increment")
    }
}

单击该按钮两次会显示以下日志(log):

Read
Calculate
Clicked
Calculate
Clicked
Calculate
Read
Calculate

然而,用remember来包装derivedStateOf会记录如下:

Read
Calculate
Clicked
Calculate
Clicked
Calculate
Read

仍然不能完全确定为什么我会看到我所看到的.

推荐答案

您的代码应该如下所示,

@Composable
fun Test() {
    var count by remember {
        mutableStateOf(0)
    }

    val moreThanOne = remember {
        derivedStateOf {
            Log.d("foo", "Calculate")
            count > 1
        }
    }

    Log.d("foo", "Read")
    moreThanOne.value

    Button(
        onClick = {
            Log.d("foo", "Clicked")
            count += 1
        }
    ) {
        Text(text = "Increment")
    }
}

请注意derivedStateOf附近额外的remember个.这不会影响日志(log)记录的结果,但是在derivedStateOf附近缺少remember需要额外的开销,因为每次运行Test都会创建一个新的derivedStateOf.在可组合函数中,您应该始终记住derivedStateOf.

从该代码中,我接收到以下内容:

D/foo: Read
D/foo: Calculate
D/foo: Clicked
D/foo: Calculate
D/foo: Clicked
D/foo: Calculate
D/foo: Read
D/foo: Clicked
D/foo: Calculate
D/foo: Clicked
D/foo: Calculate
D/foo: Clicked
D/foo: Calculate

Read个和Calculated个来自初始构图.count的值是0.

在第一次点击之后,发出Calculated,但不发出其他任何东西.这是由于Testcount的改变而有条件地失效.这是有条件的,因为只有当计算的值moreThanOne不同于先前读取的Test时,才调用Test.在本例中,它再次返回false,因此不调用Test.

再次看到第二点击Calculate,并且现在moreThanOne产生true,这使得Test的条件无效被视为真实无效,并且Test被调用以更新构图.

当调用lambda时,第三次和随后的点击只产生Calculated次(因为count改变了),但是moreThanOne的结果没有什么不同,因此Test的条件无效被忽略.

即使Read的对数在表达式moreThanOne.value之前,Calculated也出现在Read之前的原因是,moreThanOne的当前值在Test被调用之前被更新,以查看是否根本需要调用Test.然而,如果Test由于某种其他原因而无效(即,它读取了改变的某个其他状态对象),则moreThanOne将仅通过对moreThanOne.value的调用来更新.如果派生状态对象是请求重新调用Test的唯一原因,则仅在调用Test之前更新派生状态对象.如果它们返回与先前组合相同的值,则忽略无效并跳过调用.

Android相关问答推荐

如何使用视图模型触发可变状态?

Android:MethodHandle. invoke和MethodHandle. invokeExact仅从Android O( - min—api 26)开始支持

从单元测试访问RES/RAW文件

LocalContext.current的问题(@Composable调用只能从@Composable函数的上下文发生)

尽管我们不再使用GCM SDK,但应用程序已被标记为使用GCM SDK

无法加载类';com.android.build.api.extension.AndroidComponentsExtension';

如何在Android中打印到命令行

在c中更新MVVMCross中TextView的Alpha#

Android 不在后台更新位置

如何在C++中使用JNI_GetCreatedJavaVMs调用Java代码

如何在Android中使用嵌套的Recyclerview

只能从同一个库组内调用成功(引用groupId=androidx.work from groupId=My Composable)

单击按钮时不显示 Toast 消息

发布 MAUI 应用程序时出现遇到重复程序集错误

Jetpack Compose UI - 在 AlertDialog 中单击时按钮宽度会发生变化

Jetpack 组合千位分隔符视觉转换,也适用于小数

java.lang.String 类型的值 Forbidden 无法转换为 JSONObject

并行运行两个挂起函数并在第一个返回时返回

在 Jetpack Compose 中找不到 Path 的减号()

操作系统会终止已启动的服务并调用Service.onDestroy吗?