android 如何在setOnClickNode方法中处理流的收集?

9ceoxa92  于 2024-01-04  发布在  Android
关注(0)|答案(1)|浏览(112)

主要活动.kt

  1. - - - - - - - - - - EXAMPLE 1 - - - - - - - - - -
  2. override fun onCreate(savedInstanceState: Bundle?) {
  3. super.onCreate(savedInstanceState)
  4. val activityMainBinding: ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater)
  5. setContentView(activityMainBinding.root)
  6. val settingsViewModel: SettingsViewModel by viewModels()
  7. activityMainBinding.loadSettingsBtn.setOnClickListener {
  8. lifecycleScope.launch {
  9. settingsViewModel.getSettings().collect {
  10. Log.w("A8452", "MainActivity -> ${it.javaClass.name}")
  11. }
  12. }
  13. }
  14. }
  15. - - - - - - - - - - EXAMPLE 2 - - - - - - - - - -
  16. private var isCollectFired = false
  17. override fun onCreate(savedInstanceState: Bundle?) {
  18. super.onCreate(savedInstanceState)
  19. val activityMainBinding: ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater)
  20. setContentView(activityMainBinding.root)
  21. val settingsViewModel: SettingsViewModel by viewModels()
  22. activityMainBinding.loadSettingsBtn.setOnClickListener {
  23. lifecycleScope.launch {
  24. if (!isCollectFired) {
  25. isCollectFired = true
  26. settingsViewModel.getSettings().collect {
  27. Log.w("A8452", "MainActivity -> ${it.javaClass.name}")
  28. }
  29. } else
  30. settingsViewModel.getSettings()
  31. }
  32. }
  33. }

字符串

设置视图模型.kt

  1. - - - - - - - - - - Both examples use the same code in this class - - - - - - - - - -
  2. class SettingsViewModel : ViewModel() {
  3. private val mutableStateFlow: MutableStateFlow<ConnectionStatus> = MutableStateFlow(ConnectionStatus.Loading)
  4. private lateinit var settingsRepository: SettingsRepository
  5. fun getSettings(): StateFlow<ConnectionStatus> {
  6. if (!::settingsRepository.isInitialized)
  7. settingsRepository = SettingsRepository()
  8. viewModelScope.launch {
  9. settingsRepository.getSettings().collect {
  10. Log.w("A8452", "SettingsViewModel -> ${it.javaClass.name}")
  11. mutableStateFlow.emit(it)
  12. }
  13. }
  14. return mutableStateFlow
  15. }
  16. }


在示例1中,当您单击按钮时,它会从服务器加载设置。但是,如果您多次单击该按钮,它会触发多个收集。每次单击,收集都将逐渐增大,就像滚雪球一样。
有关示例1中问题的更多详细信息,请查看this question
在示例2中,我创建了一个名为isCollectFired的布尔变量。在单击按钮触发collect之前,它会检查变量。这解决了问题,尽管我不确定这是否是最佳解决方案。
现在,我感到困惑的是,在SettingsViewModel中,有一个没有检查的collect,就像我在MainActivity中实现的那样。令人惊讶的是,当用户单击按钮时,它并没有像滚雪球一样逐渐增大。你能解释一下为什么吗?
谢谢

6uxekuva

6uxekuva1#

我不知道你为什么要在一个按钮点击事件中收集一个流。对我来说,我以前不喜欢这样。我把函数和流分开,这意味着函数不需要返回实际的流。只要做它的过程并从流中发出结果。之后,UI类收集流的变化。按钮点击事件只需调用函数。
在viewModel类中

  1. private val _getReferralCodeFlow: MutableStateFlow<String?> =MutableStateFlow(null)
  2. val getReferralCodeFlow = _getReferralCodeFlow.asStateFlow()
  3. fun getReferralCode() {
  4. viewModelScope.launch {
  5. runCatching {
  6. val data = getReferralCode.execute(Unit) // assume string return
  7. _getReferralCodeFlow.value = data
  8. }.getOrElse {
  9. Timber.e(it)
  10. _getReferralCodeFlow.value = "Error occur"
  11. }
  12. }
  13. }

字符串
Activity或片段中的按钮单击

  1. btnShare.setOnClickListener {
  2. viewModel.getReferralCode()
  3. }


收集活动或片段中的流

  1. lifecycleScope.launch {
  2. viewModel.getReferralCodeFlow.collectLatest {
  3. // do something
  4. }
  5. }

展开查看全部

相关问题