0
votes

I'm trying to use room database with suspend keyword.

I can successfully insert a data into database. But after that, the insert method will not return anything, that means I can't do anything after insertion such as insert another data by the returned id.

here is my sample code:

@Dao
interface EventDao {
    ...

    @Insert
    suspend fun insert(event: Event): Long

    ...
}

class EventRepository(...) {
    ...

    suspend fun insertEvent(event: Event, personId: Long) {
        val id = eventDao.insertSync(event)

        // !!! FREEZE - the code below here will never reach !!!

        val attendee = EventAttendee(
            personId = personId,
            eventId = id
        )
        eventAttendeeDao.insert(attendee)
    }

    ...
}

class EventEditingViewModel(...) : ViewModel() {
    ...

    fun addEvent(event: Event) {
        event.userId = userId
        viewModelScope.launch {
            eventRepository.insertEvent(event, friendId)
        }
    }

    ...
}

Actually, if I remove suspend keyword, I can get the return id properly. The freezing problem will only happen when I use suspend keyword in front of insertion method in Dao class.

Logcat doesn't show any logs of this, and the app doesn't crash, so I have no idea what happened.

My room version is 2.2.1. and I've tried 2.2.2 also.

Did I do the wrong way to use suspend function in room database?

2

2 Answers

0
votes

I looked into coroutines library then found out that my insert method has been canceled cause by ViewModel deleted.

Because I built a DialogFragment and do the insertion after I click the PositiveButton of AlertDialog, so the viewModelScope has been clear before the insertion finished.

I think the solution may be the following ways:

  1. use another scope such as GlobalScope.launch instead of viewModelScope.launch

  2. dismiss the dialog after insertion.

  3. return the data to another fragment, do the insertion in another page.

In this case, I think the best choice is the first choice. It's easier and would not cause any other lifecycles' problem.

0
votes

I had the same problem as you, the easiest way to make this real-time update is to refresh the activity while you are still in the dialog box. I added these lines of code AFTER I added the user in the database ( in the OK button of the dialog box):

finish();
overridePendingTransition(0, 0);
startActivity(getIntent());
overridePendingTransition(0, 0);

Hope it helps. It worked for me!