1
votes

i have a simple Dao interface of Room database in which I have suspend functions to insert and get data from the table.

in my DBHelper class I am trying to insert data using launch - CoroutineScope but does not seem to go within the launch and the functions within the launch are not executed.

any suggestions on what I might be doing wrong please

OfflineDataDao

@Dao
interface OfflineDataDao {

    @Query("SELECT * FROM offlineDatax")
    suspend fun getOfflineData(): List<OfflineDatax>

    @Insert
    suspend fun insertOfflineData(offlineData: OfflineDatax): Long
}

Entity

@Entity
data class OfflineDatax (
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "requestJSON") val requestJSON: String?,
    @ColumnInfo(name = "requestCode") val requestCode: String?
)

DBHelper class where I am accessing the dao suspend methods

class DBHelper @Inject constructor(
    private val userDao: UserDao,
    private val offlineDataDao: OfflineDataDao
) : CoroutineScope {

    private var job: Job = Job()

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job


    fun accessDBFunction() {

        var offlineDatax =  OfflineDatax(1, "rjson", "rCode")
        addOfflineData(offlineDatax)

        getOfflineData()
    }

    fun addOfflineData(offlineDatax: OfflineDatax): Long {
        var lng: Long = 0L
        launch {
            lng = offlineDataDao.insertOfflineData(offlineDatax) // IS NOT CALLED, DOES NOT GET INTO LAUNCH
        }
        return lng
    }

    fun getOfflineData (): List<OfflineDatax> {
        var offlineData = emptyList<OfflineDatax>()
        launch {
          offlineData = offlineDataDao.getOfflineData(); // IS NOT CALLED, DOES NOT GET INTO LAUNCH
        }
        Timber.d("offlinedata " + offlineData.toString())
        return offlineData
    }
}
2
It is called, but function returns before result has came. You should make your function suspend and use withContext() or async() instead of launch() for getting result from coroutine. Launch is simply launch and forget. - Animesh Sahu
can you give me an example please on how to use async() or withContext - BRDroid

2 Answers

1
votes

Just make the function suspend, via suspend modifier and return from them directly they will suspend themselves into their own dispatcher defined in the Room library.

suspend fun addOfflineData(offlineDatax: OfflineDatax): Long =
    offlineDataDao.insertOfflineData(offlineDatax)

suspend fun getOfflineData (): List<OfflineDatax> =
     offlineDataDao.getOfflineData().also { Timber.d("offlinedata " + it.toString()) }

And call the function from any coroutine.

0
votes

Check your error logs please.

override val coroutineContext: CoroutineContext
    get() = Dispatchers.Main + job

Because of this i think that you are trying to communicate with database on Main thread.

fun getOfflineData() = withContext(Dispatchers.IO) {
    var offlineData = emptyList<OfflineDatax>()
    offlineData = offlineDataDao.getOfflineData();
    Timber.d("offlinedata " + offlineData.toString())
    offlineData // WHEN TASK FINISH THIS WILL BE RETURNED
}

and then call getOfflineData() in your launch{}