Issue
Hey I am working in kotlin flow in android. I noticed that my kotlin flow collectLatest
is calling twice and sometimes even more. I tried this answer but it didn't work for me. I printed the log inside my collectLatest
function it print the log. I am adding the code
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++}")
....
}
}
}
}
}
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
}
}
.....
}
I don't understand why this is calling two times. I am attaching logs
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
As you can see it call two times. But I load more data than it call more than twice. I don't understand why it is calling more than once. Can someone please guide me what I am doing wrong. If you need whole code, I am adding my project link.
Solution
You are using a MutableStateFlow
which derives from StateFlow
, StateFlow
has initial value, you are specifying it as an emptyList
:
var conversationMutableStateFlow = MutableStateFlow<List<String>>(emptyList())
So the first time you get data
in collectLatest
block, it is an empty list. The second time it is a list from the response.
When you call collectLatest
the conversationMutableStateFlow
has only initial value, which is an empty list, that's why you are receiving it first.
You can change your StateFlow
to SharedFlow
, it doesn't have an initial value, so you will get only one call in collectLatest
block. In ActivityViewModel
class:
var conversationMutableStateFlow = MutableSharedFlow<List<String>>()
fun fetchData() {
viewModelScope.launch {
val response = ApiInterface.create().getResponse()
conversationMutableStateFlow.emit(response.items)
}
}
Or if you want to stick to StateFlow
you can filter
your data:
viewModel.conversationMutableStateFlow.filter { data ->
data.isNotEmpty()
}.collectLatest { data ->
// ...
}
Answered By - Sergey
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.