2

I have a fragment, viewmodel and database. I call this method in the viewModel from the fragment which deletes data from database by a list of id's.

    fun deleteDefects(idList: List<Long>) {
        Log.d("RoundViewModel", idList.toString())
        viewModelScope.launch(Dispatchers.IO) {
            Log.d("RoundViewModel", idList.toString())
            ddb.dao().delAddedDefect(idList)
        }
    }

It works.. sometimes, about 2 or 3 times out of 10, deletes data. And sometimes idList in launch is empty.

2020-06-26 18:40:44.461 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [259, 260]
2020-06-26 18:40:44.464 18524-18555/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:40:47.453 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [264, 267]
2020-06-26 18:40:47.457 18524-18555/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:40:50.838 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [276, 267]
2020-06-26 18:40:50.841 18524-18555/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:40:53.896 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [276, 267, 264]
2020-06-26 18:40:53.899 18524-18555/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:40:56.947 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [259, 260, 264]
2020-06-26 18:40:56.950 18524-18555/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:41:00.023 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [264, 265, 267]
2020-06-26 18:41:00.027 18524-18554/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:41:02.731 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [264, 265]
2020-06-26 18:41:02.733 18524-18554/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:41:08.200 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [277, 267]
2020-06-26 18:41:08.201 18524-18554/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:41:11.694 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [264, 259]
2020-06-26 18:41:11.695 18524-18554/ru.debaser.projects.inspectionsheet D/RoundViewModel: [264, 259]
2020-06-26 18:41:19.528 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [265, 267]
2020-06-26 18:41:19.530 18524-18591/ru.debaser.projects.inspectionsheet D/RoundViewModel: []
2020-06-26 18:41:23.780 18524-18524/ru.debaser.projects.inspectionsheet D/RoundViewModel: [276, 267]
2020-06-26 18:41:23.782 18524-18556/ru.debaser.projects.inspectionsheet D/RoundViewModel: [276, 267]

2 Answers 2

4

The code you have should just work but it looks like you're doing something naughty when calling deleteDefects.

List<...> is a read-only interface and it does not guarantee immutability. I imagine you are modifying the idList after you pass it into the function. Something like this...

val idList = mutableListOf<Long>()
idList.add(50)
idList.add(20)

deleteDefects(idList)
idList.clear()

This is a race condition! Since concurrency has been introduced in deleteDefects, you shouldn't touch idList after you pass it in.. ever. Unless you use locks or similar.

A quick fix would be to make a defensive copy, like so.

fun deleteDefects(idListTmp: List<Long>) {
    val idList = idListTmp.toList() // Safe!
    Log.d("RoundViewModel", idList.toString())
    viewModelScope.launch(Dispatchers.IO) {
        Log.d("RoundViewModel", idList.toString())
        ddb.dao().delAddedDefect(idList)
    }
}

A proper fix, would be to not modify idList after you call deleteDefacts(idList).

Another proper fix could be to just do deleteDefacts(idList.toList()).

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

1 Comment

Thanks, it works. I passed to deleteDefects the variable that contains selectedItems from adapter vm.deleteDefects(addedDefectAdapter.selectedItems) Now I added toList() vm.deleteDefects(addedDefectAdapter.selectedItems.toList()) and everything works as I expected.
0

The thread in the caller (function deleteDefects) won't wait until the callee finish (sometimes). To test it out, wrap it in runBlocking.

Suggestion: Using await or join.

This article could help figure it out.

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.