每当设备恢复活动状态时,Kotlin Coroutines Flow with Room 再次运行

BG_*_*eMe 5 android-room android-livedata kotlin-coroutines

在使用 Kotlin Coroutines Flow、Room 和 Live Data 时,我面临着一个非常奇怪的行为。每当我关闭我的设备大约 5-10 秒然后重新打开它时,协程流程就会重新运行而没有任何触发。我不确定这是否是 Google 提供的功能。我的代码如下。

主要活动

wordViewModel = ViewModelProvider(this).get(WordViewModel::class.java)

wordViewModel.allWords.observe(this, Observer { words ->

    words?.let { adapter.setWords(it) }

})
Run Code Online (Sandbox Code Playgroud)

视图模型

class WordViewModel(private val repository: WordRepository) : ViewModel() {

    val allWords = repository.allWords.onEach { Log.v("WordViewModel", "Flow trigger again") }.asLiveData()

}
Run Code Online (Sandbox Code Playgroud)

词库

class WordRepository(private val wordDao: WordDao) {

    val allWords: Flow<List<Word>> = wordDao.getAlphabetizedWords()

    suspend fun insert(word: Word) {
        wordDao.insert(word)
    }
}
Run Code Online (Sandbox Code Playgroud)

字道

@Dao
interface WordDao {

    @Query("SELECT * from word_table ORDER BY word ASC")
    fun getAlphabetizedWords(): Flow<List<Word>>

    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun insert(word: Word)
}
Run Code Online (Sandbox Code Playgroud)

单词

@Entity(tableName = "word_table")
data class Word(@PrimaryKey @ColumnInfo(name = "word") val word: String)
Run Code Online (Sandbox Code Playgroud)

V/WordViewModel: Flow trigger again当我关闭我的设备大约 5-10 秒并重新打开它时,LogCat将再次打印出来。另外,我用来测试的设备是在 Android 10 上运行的 Sony XZ2。

如果有人知道为什么会这样,请帮助我理解。感谢和抱歉我的英语。

编辑

作为@Alex Krafts 的回答,此功能由 Google 提供。但是因为我的 Kotlin Coroutines Flow 会与网络请求结合。因此,当设备处于活动状态时,我不希望它再次运行。我为这种情况编写了一个自定义的 asLiveData() 扩展函数,如下所示。

实时数据扩展

fun <T> Flow<T>.asLiveData(scope: CoroutineScope): LiveData<T> {
    val liveData = MutableLiveData<T>()
    scope.launch {
        collect {
            liveData.value = it
        }
    }
    return liveData
}
Run Code Online (Sandbox Code Playgroud)

视图模型

class WordViewModel(private val repository: WordRepository) : ViewModel() {

    val allWords = repository.allWords.onEach { Log.v("WordViewModel", "Flow trigger again") }.asLiveData(viewModelScope)

}
Run Code Online (Sandbox Code Playgroud)

Ale*_*fts 2

这个功能确实是Google提供的。您正在提供MainActivity(此),如下LifecycleOwner所示

wordViewModel.allWords.observe(this, Observer { words ->
Run Code Online (Sandbox Code Playgroud)

因此,当您关闭设备屏幕时,Activity(由于其自身的生命周期)将停止观察allWords,并在您重新打开设备屏幕时再次观察它。这就是您的日志的来源。

文档中

取消后,如果LiveData再次激活,则会重新执行上游流量收集。