为什么在 kotlin 中流收集调用超过两次?

Viv*_*odi 4 android kotlin kotlin-coroutines kotlin-flow kotlin-stateflow

嘿,我正在 android 中的 kotlin flow 工作。我注意到我的 kotlin 流程collectLatest调用了两次,有时甚至更多。我尝试过这个答案,但它对我不起作用。我在我的函数中打印了日志,collectLatest它打印了日志。我正在添加代码

MainActivity.kt

class MainActivity : AppCompatActivity(), CustomManager {

    private val viewModel by viewModels<ActivityViewModel>()
    private lateinit var binding: ActivityMainBinding
    private var time = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        setupView()
    }

    private fun setupView() {
        viewModel.fetchData()

        lifecycleScope.launchWhenStarted {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.conversationMutableStateFlow.collectLatest { data ->
                    Log.e("time", "${time++}")
                   ....
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ActivityViewModel.kt

class ActivityViewModel(app: Application) : AndroidViewModel(app) {

    var conversationMutableStateFlow = MutableStateFlow<List<ConversationDate>>(emptyList())

    fun fetchData() {
        viewModelScope.launch {
            val response = ApiInterface.create().getResponse()
            conversationMutableStateFlow.value = response.items
        }
    }

   .....
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么这会调用两次。我正在附加日志

2022-01-17 22:02:15.369 8248-8248/com.example.fragmentexample E/time: 0
2022-01-17 22:02:15.629 8248-8248/com.example.fragmentexample E/time: 1
Run Code Online (Sandbox Code Playgroud)

如您所见,它调用了两次。但我加载的数据比它调用的多两倍多。我不明白为什么它不止一次地打电话。有人可以指导我我做错了什么吗?如果您需要完整代码,我将添加我的项目链接

Ser*_*gey 9

您正在使用MutableStateFlow派生自 的a StateFlowStateFlow具有初始值,您将其指定为emptyList

var conversationMutableStateFlow = MutableStateFlow<List<String>>(emptyList())
Run Code Online (Sandbox Code Playgroud)

所以当你第一次进入data块时collectLatest,它是一个空列表。第二次是响应中的列表。

当您collectLatest致电conversationMutableStateFlow(这是一个空列表)时,这就是您首先接收它的原因。

您可以将您的StateFlowto更改为SharedFlow,它没有初始值,因此您在collectLatest块中只会收到一次调用。在ActivityViewModel班上:

var conversationMutableStateFlow = MutableSharedFlow<List<String>>()

fun fetchData() {
    viewModelScope.launch {
        val response = ApiInterface.create().getResponse()
        conversationMutableStateFlow.emit(response.items)
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您想坚持使用StateFlowfilter的数据:

viewModel.conversationMutableStateFlow.filter { data ->
                data.isNotEmpty()
            }.collectLatest { data ->
                // ...
            }
Run Code Online (Sandbox Code Playgroud)