0

I am making a dynamic UI using kotlin and Jetpack compose and storing the information in an object box database.

The aim is that i will have a composable that starts off with 1 initial item that is empty and when the contents of the textbox have been filled in would allow the red "+" button to be clicked and then another textfield would appear. These values will need to be able to be edited constantly all the way until the final composable value is stored. The button changes colour currently and the states are fine with the button so i can add and remove rows

Empty list composable

The data comes in as a string and is converted into a Hashmap<Int, String>. The int is used to store the position in the map being edited and the string would be the text value.

Using log messages i see that the information is updated in the list and for recomp sake i instantly store the value of the edited list in a converted json string.

At the moment:

  1. When i scroll past the composable it resets and looks like the initial state (even if i have added multiple rows)
  2. Log messages show that my hashmap has the values from before e.g. {"0":"asdfdsa"} but the previous positions are ignored and as the previous information would still be present but not shown on the UI when i enter it into the first field again (the others are not visible at the time) {"0":"asdfdsa","0":"hello"}. This would later cause an error when trying to save new data to the list because of the duplicate key

In the composables my hashmap is called textFields and is defined like this. Number is used to determine how many textfields to draw on the screen

val textFields = remember { getDataStringToMap(data.dataItem.dataValue) }
val number = remember { mutableStateOf(textFields.size) }

the method to getDataStringToMap is created like this

private fun getDataMapToString(textFieldsMap: HashMap<Int, String>): String {
    val gson = Gson()
    val newMap = hashMapOf<Int, String>()
    for (value in textFieldsMap){
        if (value.value .isNotBlank()){
            newMap[value.key] = value.value
        }
    }
    return gson.toJson(newMap)
}

and the method to getDataStringToMap is created like this (I explicitly define the empty hashmap type because its more readable for me if i can see it)


private fun getDataStringToMap(textsFieldsString: String): HashMap<Int, String> {
    val gson = Gson()
    return if (textsFieldsString.isBlank()) {
        hashMapOf<Int, String>(0 to "")
    } else {
        val mapType = HashMap<Int, String>().javaClass
        gson.fromJson(textsFieldsString, mapType)
    }

the composables for the textfields are called like this

items(number.value) { index ->
    listItem(
        itemValue = textFields[index].orEmpty(),
        changeValue = {
            textFields[index] = it
            setDataValue(getDataMapToString(textFields))
        },
        addItem = {
            columnHeight.value += itemHeight
            scope.launch {
                scrollState.animateScrollBy(itemHeight)
            }
        },
        deleteItem = {
            columnHeight.value -= itemHeight
            scope.launch {
                scrollState.animateScrollBy(-itemHeight)
            }
        },
        lastItem = index == number.value - 1,
        index = index
    )
}

Edited 30/12/2022

Answer from @Arthur Kasparian solved issues. Change to rememberSaveable retains the UiState even on scroll and recomp.

Now just to sort out which specific elements are removed and shown after :D

3
  • Have you tried using rememberSaveable instead of just remember? Commented Dec 30, 2022 at 6:33
  • 1
    That worked! when i switch the to rememberSaveable for the textFields, number definition and columnHeight (i use this to define how big the section should be, Its a lazy list in a lazy list so needs dimensions) please add your suggestion as an an answer so i can upvote you for it @ArthurKasparian Commented Dec 30, 2022 at 17:29
  • Done! Sorry for the delay, and a slightly early happy new year to you! Commented Dec 31, 2022 at 1:03

1 Answer 1

1

The problem is that remember alone does not save values on configuration changes, whereas rememberSaveable does.

You can read more about this here.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.