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

Kotlin Coroutines Flow with Room run again whenever device back to active

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

MainActivity

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

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

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

})

WordViewModel

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

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

}

WordRepository

class WordRepository(private val wordDao: WordDao) {

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

    suspend fun insert(word: Word) {
        wordDao.insert(word)
    }
}

WordDao

@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)
}

@Entity(tableName = "word_table")
data class Word(@PrimaryKey @ColumnInfo(name = "word") val word: String)

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

如果有人知道为什么会这样,请帮助我理解。谢谢,对不起我的英语。

编辑

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

LiveDataExtension

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

WordViewModel

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

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

}

这个功能确实是由Google提供的。您在

中提供 MainActivity(this) 作为 LifecycleOwner
wordViewModel.allWords.observe(this, Observer { words ->

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

来自documentation

After a cancellation, if the LiveData becomes active again, the upstream flow collection will be re-executed.