每当设备恢复活动时,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
并在您重新打开设备屏幕时再次观察它。这就是您的日志的来源。
After a cancellation, if the LiveData becomes active again, the upstream flow collection will be re-executed.
我在使用 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
并在您重新打开设备屏幕时再次观察它。这就是您的日志的来源。
After a cancellation, if the LiveData becomes active again, the upstream flow collection will be re-executed.