2

嘿,我正在 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++}")
                   ....
                }
            }
        }
    }
}

活动视图模型.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
        }
    }

   .....
}

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

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

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

4

2 回答 2

2

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

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

因此,当您第一次进入datacollectLatest时,它是一个空列表。第二次是来自响应的列表。

当您调用只有初始值时,它是一个空列表,这就是您首先接收它的原因collectLatestconversationMutableStateFlow

你可以改变你的StateFlowto SharedFlow,它没有初始值,所以你只会得到一个collectLatest块调用。在ActivityViewModel课堂上:

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

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

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

viewModel.conversationMutableStateFlow.filter { data ->
                data.isNotEmpty()
            }.collectLatest { data ->
                // ...
            }
于 2022-01-18T10:33:55.877 回答
1

原因是 collectLatest 之类的背压。如果您一次传递多个项目,流将只收集最新的,但如果在发射之间有一段时间,流将收集每个像最新的

已编辑:您确实需要阅读有关 MVVM 架构的信息。

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding

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

private fun setupView() {
    if (supportFragmentManager.findFragmentById(R.id.fragmentView) != null) 
        return
    
    supportFragmentManager
        .beginTransaction()
        .add(R.id.fragmentView, ConversationFragment())
        .commit()
}
}

删除ActivityViewModel并将该逻辑添加到FragmentViewModel. 还要注意你不需要 use AndroidViewModel,如果你可以使用 plain ViewModel。仅在AndroidViewModel您需要访问Application或其Context

于 2022-01-17T22:59:35.807 回答