Android Библиотека комнат с Kotlin Flow toList () не работает - PullRequest
2 голосов
/ 21 июня 2020

Я сделал простой пример приложения с использованием Room и Flows:

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val build = Room.databaseBuilder(this, FinanceDatabase::class.java, "database.db")
            .fallbackToDestructiveMigration()
            .build()
    GlobalScope.launch {
        build.currencyDao().addCurrency(CurrencyLocalEntity(1))
        val toList = build.currencyDao().getAllCurrencies().toList()
        Log.d("test", "list - $toList")
    }
}
}

@Entity(tableName = "currency")
data class CurrencyLocalEntity(
        @PrimaryKey(autoGenerate = true)
        @ColumnInfo(name = "currencyId")
        var id: Int
) {
    constructor() : this(-1)
}

@Dao
interface CurrencyDao {

@Query("SELECT * FROM currency")
fun getAllCurrencies(): Flow<CurrencyLocalEntity>

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun addCurrency(currency: CurrencyLocalEntity)
}

@Database(entities = [CurrencyLocalEntity::class], version = 1)
abstract class FinanceDatabase : RoomDatabase() {
    abstract fun currencyDao(): CurrencyDao
}

Я хочу использовать функцию toList(), как в коде выше, но что-то идет не так, и даже журнал не печатается. В то же время использование collect() отлично работает и дает мне все записи.

Может ли кто-нибудь объяснить мне, что не так? Спасибо.

Ответы [ 3 ]

1 голос
/ 22 июня 2020

Здесь есть несколько ошибок, но я остановлюсь на основной проблеме.

Flow, возвращаемые room, выдают результат запроса каждый раз, когда изменяется база данных. (Это может быть ограничено изменениями таблицы, а не всей базы данных).

Поскольку база данных может измениться в любой момент в будущем, Flow не будет (более или менее) никогда не завершится, потому что изменение всегда можно

Ваш вызов toList() на возвращенном Flow будет приостановлен навсегда, поскольку Flow никогда не завершается. Это концептуально имеет смысл, поскольку Room не может предоставить вам список всех изменений, которые произойдут, не дожидаясь, пока они произойдут. Я уверен, что вы знаете, почему collect дает вам записи, а toList() - нет.

Вероятно, вам нужно вот это.

@Query("SELECT * FROM currency")
fun getAllCurrencies(): Flow<List<CurrencyLocalEntity>>

С этим вы можете получить первый результат запроса с помощью Flow<...>.first().

1 голос
/ 22 июня 2020

Поток в комнате предназначен для наблюдения за изменениями в таблице.

Каждый раз, когда в таблицу вносятся какие-либо изменения, независимо от того, какая строка изменяется, запрос будет повторно запущен, и поток будет выдан снова.

Однако такое поведение базы данных также означает, что если мы обновим несвязанную строку, наш Flow будет генерировать снова с тем же результатом. Поскольку триггеры базы данных SQLite разрешают уведомления только на уровне таблицы, а не на уровне строки, Room не может знать, что именно изменилось в данных таблицы

0 голосов
/ 22 июня 2020
**getAllCurrencies()** function should be suspend.

Please check the syntax to collect List from Flow: 

suspend fun <T> Flow<T>.toList(
    destination: MutableList<T> = ArrayList()
): List<T> (source)

https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/to-list.html
...