2

I have a composable function that looks something like this:


@Composable
fun listScreen(context: Context, owner: ViewModelStoreOwner) {
    val repository = xRepository(getAppDatabase(context).xDao()
    val listData by repository.readAllData.observeAsState(emptyList())
    // repository.readAllData returns LiveData<List<xEntity>>
   // listData is a List<xEntity>
    
    LazyColumn(){ 
        items(listData.size) {
            Card {
                  Text(listData[it].name)
                  Text(listData[it].hoursLeft.toString())
                  Button(onClick = {updateInDatabase(owner, name = listData[it], hoursLeft = 12)}) {...}
                  }
        }
    }

}

fun updateInDatabase(owner: ViewModelStoreOwner, name: String, hoursLeft: Int) {
     val xViewModel....
     val newEntity = xEntity(name=name, hoursLeft = Int)
     xViewModel.update(newEntity)
}

and as you propably can guess, the LazyColumn doesn't refresh after modification of entity, is there a way to update listData after every update of entity?

edit:

class xRepository(private val xDatabaseDao) {
    val readAllData: LiveData<List<xEntity>> = xDatabaseDao.getallXinfo()
    ...
    suspend fun updatePlant(x: xEntity) {
        plantzDao.updateX(x)
    }
}

interface xDatabaseDao {
    @Query("SELECT * FROM xInfo ORDER BY id DESC")
    fun getAllXInfo(): LiveData<List<xEntity>>
    ....
    
    @Update(onConflict = OnConflictStrategy.REPLACE)
    suspend fun updateX(x: xEntity?)
}

modification of entity:


fun updatePlantInDatabase(owner: ViewModelStoreOwner, name: String, waterAtHour: Int, selectedDays: ArrayList<Int>) {
    val xViewModel: xViewModel = ViewModelProvider(owner).get(xViewModel::class.java)
    val new = xEntity(name = name, waterAtHour = waterAtHour, selectedDays = selectedDays)
    xViewModel.updatePlant(new)
}
JustSightseeing
  • 1,460
  • 3
  • 17
  • 37
  • why your `TextField` only has a single parameter, is is read only? Show `readAllData` and how you modify the data – Phil Dukhov Sep 12 '21 at 04:03
  • 1. my mistake, there are no textFields, I meant Text 2. I will update the post with info about readAllData and modification – JustSightseeing Sep 12 '21 at 10:19
  • I still have no idea how your `xViewModel` connected to `repository.readAllData`, and why it should trigger recomposition – Phil Dukhov Sep 12 '21 at 10:22
  • basically the only thing I'm trying to do is "refresh" the list that contains all the info about xEntities after one of the entities is modified – JustSightseeing Sep 12 '21 at 10:27
  • From the compose point of view you're doing all right, look for why your `readAllData` doesn't update `LiveData` value after database update – Phil Dukhov Sep 12 '21 at 10:40
  • listData is initialised at the beginning of the composable function and I would need to probably "refresh" it's value (it changes when I add/delete new Entity but not on modification) – JustSightseeing Sep 12 '21 at 16:44
  • Yes, check out [this answer](https://stackoverflow.com/a/49022687/3585796) – Phil Dukhov Sep 13 '21 at 04:45
  • I also think that this [article](https://medium.com/firebase-tips-tricks/how-to-read-data-from-room-using-kotlin-flow-in-jetpack-compose-7a720dec35f5), might help. – Alex Mamo May 17 '22 at 07:19

2 Answers2

1

I use mutableStateOf to wrap fields that need to recomposed. Such as

class TestColumnEntity(
    val id: String,
    title: String = ""
){
    var title: String by mutableStateOf(title)
}

View:

        setContent {
            val mData = mutableStateListOf(
                TestColumnEntity("id_0").apply { title = "cnm"},
                TestColumnEntity("id_1").apply { title = "cnm"},
                TestColumnEntity("id_2").apply { title = "cnm"},
                TestColumnEntity("id_3").apply { title = "cnm"},
                TestColumnEntity("id_4").apply { title = "cnm"},
                TestColumnEntity("id_5").apply { title = "cnm"},
            )
            Column {
                Button(onClick = {
                    mData.add(TestColumnEntity("id_${Random.nextInt(100) + 6}").apply { title = "ccnm" })
                }) {
                    Text(text = "add data")
                }
                Button(onClick = {
                    mData[1].title = "test_${Random.nextInt(100)}"
                }) {
                    Text(text = "update data")
                }
                TestLazyColumn(data = mData, key = {index, item ->
                    item.id
                }) {
                    Text(text = it.title)
                }
            }
        }

It works in my testcase

0

If you want to update lazy column (say recompose in jetpack compose) so use side effects. Put list getting function in side effect (Launch Effect or other side effects) when list is change side effect automatic recompose your function and show updated list.

Rohit Jakhar
  • 1,231
  • 2
  • 12
  • 21