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

9ceoxa92  于 5个月前  发布在  Android
关注(0)|答案(1)|浏览(41)

主要活动.kt

- - - - - - - - - - EXAMPLE 1 - - - - - - - - - -

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val activityMainBinding: ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(activityMainBinding.root)

    val settingsViewModel: SettingsViewModel by viewModels()
    activityMainBinding.loadSettingsBtn.setOnClickListener {
        lifecycleScope.launch {
            settingsViewModel.getSettings().collect {
                Log.w("A8452", "MainActivity -> ${it.javaClass.name}")
            }
        }
    }
}

- - - - - - - - - - EXAMPLE 2 - - - - - - - - - -

private var isCollectFired = false

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val activityMainBinding: ActivityMainBinding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(activityMainBinding.root)

    val settingsViewModel: SettingsViewModel by viewModels()
    activityMainBinding.loadSettingsBtn.setOnClickListener {
        lifecycleScope.launch {
            if (!isCollectFired) {
                isCollectFired = true
                settingsViewModel.getSettings().collect {
                    Log.w("A8452", "MainActivity -> ${it.javaClass.name}")
                }
            } else
                settingsViewModel.getSettings()
        }
    }
}

字符串

设置视图模型.kt

- - - - - - - - - - Both examples use the same code in this class - - - - - - - - - -

class SettingsViewModel : ViewModel() {

    private val mutableStateFlow: MutableStateFlow<ConnectionStatus> = MutableStateFlow(ConnectionStatus.Loading)
    private lateinit var settingsRepository: SettingsRepository

    fun getSettings(): StateFlow<ConnectionStatus> {
        if (!::settingsRepository.isInitialized)
            settingsRepository = SettingsRepository()

        viewModelScope.launch {
            settingsRepository.getSettings().collect {
                Log.w("A8452", "SettingsViewModel -> ${it.javaClass.name}")
                mutableStateFlow.emit(it)
            }
        }

        return mutableStateFlow
    }

}


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

6uxekuva

6uxekuva1#

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

private val _getReferralCodeFlow: MutableStateFlow<String?> =MutableStateFlow(null)
val getReferralCodeFlow = _getReferralCodeFlow.asStateFlow()

fun getReferralCode() {
    viewModelScope.launch {
        runCatching {
            val data = getReferralCode.execute(Unit) // assume string return
            _getReferralCodeFlow.value = data
        }.getOrElse {
            Timber.e(it)
            _getReferralCodeFlow.value = "Error occur"
        }
    }
}

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

btnShare.setOnClickListener {
    viewModel.getReferralCode()
}


收集活动或片段中的流

lifecycleScope.launch { 
    viewModel.getReferralCodeFlow.collectLatest { 
        // do something
    }
}

相关问题