使用协程流程时房间冻结->收集

时间:2019-11-11 12:21:28

标签: android kotlin android-room kotlin-coroutines flow

我正在使用带有协程支持(v。1.3.2)的Room(v。2.2.1)和以下设置

@Entity(tableName = "simple_table")
data class SimpleEntity(
    @PrimaryKey(autoGenerate = true) val id: Long = 0
) 

@Dao
interface SimpleDao {
    @Query("SELECT * FROM simple_table WHERE id = :id")
    fun getRecord(id: Long): Flow<SimpleEntity?>

    @Insert
    suspend fun insert(entity: SimpleEntity)
}

然后将数据插入具有自动生成ID 1的simple_table中之后,我尝试查询

db.simpleDao.getRecord(1).collect {
  //fetch data
}
db.close()

db.close()永远不会到达。它只是冻结在collect()方法中。如果我将代码更改为

db.simpleDao.getRecord(1).first {
  //fetch data
}

db.simpleDao.getRecord(1).take(1).collect {
  //fetch data
}

然后它可以正常工作。但是,为什么简单的collect()永远不会结束执行?我在会议室配置中错过了什么以使其能够正常工作?

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题并且已经解决了

.collect 之后的代码 {} 在同一个协程中不起作用! 如果你这样写:

    MainScope().launch {

        db.simpleDao.getRecord(1).collect {
            //fetch data
        }
        /**
         * My other code that will be freezed
         * */

    }

你应该这样写:

    MainScope().launch {

        launch { //new coroutine
            db.simpleDao.getRecord(1).collect {
                //fetch data
            }
            // No code here
        }
        /**
         * My other code that will not be freezed
         * */

    }

我认为这都是因为 slot.awaitPending() 被调用以等待新值进行收集。

答案 1 :(得分:-1)

改为声明您的参数,。 我已经检查了 first() take()函数(效果很好),并与 count()比较(不起作用)。区别在于参数。

尝试更改:

flow.collect {
   //fetch data
}

收件人:

flow.collect { value ->
   //fetch data
}

我不知道为什么,但这对我有用。

编辑:

first() take()函数引发 AbortFlowException()。试试这个:

try {
   db.simpleDao.getRecord(1).collect {
      //fetch data
      throw AbortFlowException()
   }
} catch (e: AbortFlowException) {
   // Do nothing
}
db.close()