1

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
    }
}
BRDroid
  • 3,920
  • 8
  • 65
  • 143
  • 1
    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 Jun 01 '20 at 08:51
  • can you give me an example please on how to use async() or withContext – BRDroid Jun 01 '20 at 09:06

2 Answers2

1

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.

Animesh Sahu
  • 7,445
  • 2
  • 21
  • 49
  • hi, `offlineData ` in Timber is not defined, how do we get data `also` what data is coming – BRDroid Jun 01 '20 at 09:20
  • thank you so much, that worked for me. its an off topic question, but I if I want to read the changes happening that table. lets say, I just keep inserting here data into the table. and I want to listen to changes happening on that table, how can I do that please. suggestions should be very helpful – BRDroid Jun 01 '20 at 09:41
  • @BRDroid https://stackoverflow.com/questions/50915186/how-to-read-data-and-listen-to-changes-from-room-database-in-a-service and https://stackoverflow.com/questions/48978145/observing-changes-in-room-database-table-using-itemkeyeddatasource – Animesh Sahu Jun 01 '20 at 09:43
  • I am not using LiveData and MVVM, my project is heavily built of MVP and rx java. but as I am using coroutines in my Dao's, what do you recommend, – BRDroid Jun 01 '20 at 09:46
  • @BRDroid you can use Flow of coroutines right? https://stackoverflow.com/questions/54454829/room-with-kotlin-coroutines-observe-db-changes – Animesh Sahu Jun 01 '20 at 09:50
  • yes that should work I think, will try that, thank you so much, you have been very very helpful.. – BRDroid Jun 01 '20 at 09:52
0

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{}

Apollo
  • 420
  • 3
  • 6