为什么 Compose 状态不只更新 UI 组件,而且还重新启动 Android Studio 中的逻辑代码?

Hel*_*oCW 1 android android-studio android-jetpack-compose

在Compose之前,我使用LiveDataUI组件和数据之间的连接,当数据类型LiveData发生变化时,UI组件将被更新。当我使用 Compose 后,我被告知这MutableState<T>就像LiveData,但它是在 Compose 中使用的。

在下面的代码中,Aval countMutableState<T>在第1部分中输入的,因此当我单击第3部分中的按钮时,第2部分中的文本将被更改。上面的过程很容易理解,就像我之前使用LiveData一样。

但是"3 times clicked"当我点击按钮3次时就会显示,我不明白为什么会启动第4部分,你知道if (count.value == 3)...这是一个逻辑代码,它与任何UI组件无关。

1:是否意味着系统会观察与 相关的所有代码val count,并在count.value发生变化时自动运行它?

2:当我点击第3部分中的按钮时,第5部分总是会重新启动吗?

代码A

@Composable
fun Counter() {

    Column {
        //Part 1
        val count = remember { mutableStateOf(0) }

       //Part 2
        Text(
            text = "I've been clicked ${count.value} times",
        )

        //Part 3
        Button(onClick = { count.value++ }) {
            Text("Click me")
        }
       
        //Part 4       
        if (count.value == 3) {
            Log.e("My","This is test")
            Toast.makeText(LocalContext.current, "3 times clicked", Toast.LENGTH_LONG).show()
        }

        //Part 5
        Log.e("My","Is it always displayed?")
        Toast.makeText(LocalContext.current, "Is it always displayed", Toast.LENGTH_LONG).show()
    }
}



class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            BasicsCodelabTheme {
                Surface{
                    Counter()
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

新增内容

在代码 B 中,我知道当 的值displayFullItemByID发生变化时,A 部分将重新启动。

  1. 当 的值displayFullItemByID发生变化时,B 部分是否会重新启动?

  2. 当 的值displayFullItemByID发生变化且等于 5 时,C 部分是否会重新启动?

代码B

class VoiceAdapters (private val aHomeViewModel: HomeViewModel) {

     fun bind(inputMVoice: MVoice) {                        
           aHomeViewModel.displayFullItemByID.observe(mLifecycleOwner) {
                //Part A
                _isDisplayed.value = inputMVoice.id == it
            }
 
               //Part B
            Log.e("My","Can I relaunched in Part B")
            
            if (aHomeViewModel.displayFullItemByID.value==5) {
                //Part C
                Log.e("My","Can I relaunched in Part C") 
            }
    }

}

class HomeViewModel() : AndroidViewModel(mApplication) {
    private val _displayFullItemByID = MutableLiveData(-1)
    val displayFullItemByID: LiveData<Int> = _displayFullItemByID
    ...
}
Run Code Online (Sandbox Code Playgroud)

ian*_*ake 6

A是副作用Toast的一个示例- 影响可组合项本身之外的设备状态的东西(在这种特殊情况下,让系统显示一条 toast 消息)。

根据文档,组合应该没有副作用 -心理模型的核心部分是函数的实际组合@Composable可能会发生很多很多次。

所以是的,任何读取count.value都会导致该可组合函数重组(即再次执行)。然而,对于Toast消息来说,这可能不是您想要的 - 您不需要多条 toast 消息,只需要值第一次更改为 3 时的消息。

这是 的用例之一LaunchedEffect,它仅在输入参数更改时运行其块:

// This LaunchedEffect only runs when count.value changes,
// thus ensuring that only a single call to Toast.makeText()
// happens for each time the count changes to exactly 3
LaunchedEffect(count.value) {
    if (count.value == 3) {
        Toast.makeText(LocalContext.current, "3 times clicked", Toast.LENGTH_LONG).show()
    }
}
Run Code Online (Sandbox Code Playgroud)