Issue
Situation
Example I have 2 activities, Activity Menu
and Activity Detail
. Flow system is, I go to Activity Menu
, click a button to Activity Detail
. I updated the data from Activity Detail
. When press Back Button at the phone, only Resource Success
trigger, not the Resource Loading
.
Codes Relevant
Resource class
sealed class Resource<T>(
val data: T? = null,
val message: String? = null,
val messageInt: Int? = null,
val code: Int? = null,
val errorReader: Reader? = null,
) {
class Initialize<T> : Resource<T>()
class Loading<T>(data: T? = null) : Resource<T>(data)
class Success<T>(data: T?) : Resource<T>(data)
class Error<T>(
message: String? = null,
messageInt: Int? = null,
data: T? = null,
code: Int? = null,
errorReader: Reader? = null
) :
Resource<T>(data, message, messageInt, code, errorReader)
}
At ViewModel
private val _itemList = MutableStateFlow<Resource<Int>>(Resource.Initialize())
val itemList: StateFlow<Resource<Int>> = _itemList
init {
viewModelScope.launch {
getItemList()
}
}
suspend fun getItemList() = viewModelScope.launch {
_itemList.emit(Resource.Loading())
val data = withContext(ioDispatcher + coroutineExceptionHandler) {
return@withContext quickSave.getInt(Constant.BROKEN_TOTE_LIST_COUNT, 0)
}
//Only this Success trigger for 2nd time
_itemList.emit(Resource.Success(data = data))
}
At the Activity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityToteBrokenBinding.inflate(layoutInflater)
val root = binding.root
setContentView(root)
startLifeCycle()
}
private fun startLifeCycle() {
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
launch {
collectItemList()
}
}
}
}
private suspend fun collectItemList() {
viewModel.itemList.collectLatest {
when (it) {
is Resource.Initialize -> {
}
is Resource.Loading -> {
Log.i("???","Resource Loading")
showLoading()
}
is Resource.Success -> {
Log.i("???","Resource Success")
handleSuccess()
hideLoading()
}
is Resource.Error -> {
hideLoading()
}
}
}
}
Here is the Output
---------------------------- PROCESS STARTED (30051) for package com.company.com ----------------------------
2022-09-29 12:21:51.977 30051-30051 ??? com.company.com I Resource Loading
2022-09-29 12:21:52.137 30051-30051 ??? com.company.com I Resource Success
2022-09-29 12:22:10.839 30051-30051 ??? com.company.com I Resource Success
The Output not trigger Resource Loading
. How to make it trigger again every time I back from the Activity Detail
?
Solution
First as in your getItemList()
method you are already using viewModelScope.launch
, you can remove the suspend
modifier from it.
The 2nd time success is not getting triggered from your view model function but because you are using lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED)
hence the flow is getting collected again after coming back to the activity.
So in your menu activity you can override onResume
method, and in that you can call the view model function getItemList()
, which will then emit in your expected sequence.
Only drawback is that it will get trigger on every onResume, even when Lock/Unlock happens or you are returning to the app from background.
Answered By - Ankit Wala
Answer Checked By - Gilberto Lyons (JavaFixing Admin)