android-jetpack-compose

How to observe map change in jetpack compose?


I wanna do some network request and show the list results in jetpack compose. I pass the request params to list widget. But the list widget cannot recompose after the map changed, even added a key.

Below is a little demo: The int value should change after tapped the button.

Please help me to fix this.

@Preview
@Composable
fun test() {
    var map by remember { mutableStateOf(mapOf<String, Any>()) }
    Column {
        Button(
            onClick = {
                map = HashMap(map)
            }
        ) {
            Text(
                text = "Tap"
            )
        }

        key(map) { testWidget1(map = map) }
    }

}

@Composable
fun testWidget1(map: Map<String, Any>) {
    var testInt by remember { mutableStateOf(0) }
    LaunchedEffect(map) {
        testInt += 1
        request()
    }
    Text(
        text = "$testInt"
    )


}

fun request() {

}

Solution

  • Objective:
    The goal was to update an integer value upon a button tap and ensure the UI (specifically testWidget1) responds accordingly.

    Issue Identified:
    On each button click, the map was being replaced with a new HashMap instance instead of updating the existing one. As a result, testWidget1 was not being recomposed, since the recomposition depends on observing changes to the map object itself.

    Solution Implemented:
    To address this, I modified the logic to update the existing map rather than reassigning it. I introduced a counter that increments with each button click. This counter is used to generate and insert a new key-value pair into the existing map.

    By updating the map in place—while retaining existing entries—testWidget1 now detects the changes and recomposes with the new values.

    Each click adds new entries like key1, key2, key3, and so on, which ensures the map is consistently modified and triggers the expected UI updates.

    @Preview
    @Composable
    fun test() {
        var map by remember { mutableStateOf(mapOf<String, Any>()) }
        var count by remember { mutableStateOf(0) }
        Column {
            Button(
                onClick = {
                    count += 1
                    map = map + ("key$count" to "value")
                }
            ) {
                Text(
                    text = "Tap"
                )
            }
             testWidget1(map = map)
        }
    
    }
    
    @Composable
    fun testWidget1(map: Map<String, Any>) {
        var testInt by remember { mutableStateOf(0) }
        LaunchedEffect(map) {
            testInt += 1
            request()
        }
        Text(
            text = "$testInt"
        )
    
    
    }
    
    fun request() {
    
    }