Noushad Chullian
07/06/2021, 6:41 AMoverride suspend fun getProducts()=flow<State<List<ProductListFromEntity>>> {
try {
val it = productDao.getProducts()
if (it.isEmpty()) {
loadProducts()
} else {
emit(State.success(it))
}
}catch(e:Exception){
emit(State.error(e.localizedMessage.toString()))
e.printStackTrace()
}
}
//Dao function
@Query("SELECT product.productId, product.productCode, product.name FROM Product product")
abstract suspend fun getProducts(): List<ProductListFromEntity>
//viewModel
suspend fun getProducts() {
productRepository.getProducts().collectLatest {
when (it) {
is State.Error -> {
_productListStates.value =
ProductListStates.Error(it.message, UIComponentType.Dialog())
}
is State.Success -> {
parseGivenProductList(it.data)
}
}
}
}
i am calling this function from viewmodel (android), But it is always throwing error saying, Child of the scoped flow was cancelled
without any stacktrace. Am i doing anything wrong here...gildor
07/06/2021, 6:52 AMwithout any stacktraceIt’s strange, it should have at least some stacktrace, could you show full error message
gildor
07/06/2021, 6:55 AMproductDao.getProducts()
as I understand from your example it should return Flow, but you use it a way that it returns ListNoushad Chullian
07/06/2021, 6:56 AMgildor
07/06/2021, 6:59 AMgildor
07/06/2021, 6:59 AMState.error(e.localizedMessage.toString()))
pass whole exception:
State.error(e)
Noushad Chullian
07/06/2021, 7:00 AMgildor
07/06/2021, 7:00 AMcause
Noushad Chullian
07/06/2021, 7:04 AMkotlinx.coroutines.flow.internal.ChildCancelledException: Child of the scoped flow was cancelled
this is the Exception returning, no stackTrace foundgildor
07/06/2021, 7:11 AMgildor
07/06/2021, 7:11 AMNoushad Chullian
07/06/2021, 7:11 AMgildor
07/06/2021, 7:12 AMgildor
07/06/2021, 7:12 AMgildor
07/06/2021, 7:12 AMNoushad Chullian
07/06/2021, 7:13 AMgildor
07/06/2021, 7:14 AMgildor
07/06/2021, 7:15 AMcause
and check, maybe there is stacktraceNoushad Chullian
07/06/2021, 7:15 AMgildor
07/06/2021, 7:16 AMloadProducts
is doing, there is no related code in your exampleNoushad Chullian
07/06/2021, 7:16 AMproductDao.getProducts()
gildor
07/06/2021, 7:17 AMNoushad Chullian
07/06/2021, 7:17 AMloadProducts
is a network call to fetch from server and it is working, because iam using that one to store into my sqlitegildor
07/06/2021, 7:18 AMNoushad Chullian
07/06/2021, 7:18 AMgildor
07/06/2021, 7:18 AMgildor
07/06/2021, 7:19 AMgildor
07/06/2021, 7:19 AM}catch(e:Exception){
do
}catch(e: CancellationException){
throw e
}catch(e:Exception){
gildor
07/06/2021, 7:20 AMNoushad Chullian
07/06/2021, 7:20 AMNoushad Chullian
07/06/2021, 7:24 AMgildor
07/06/2021, 7:26 AMNoushad Chullian
07/06/2021, 7:27 AMgildor
07/06/2021, 7:29 AMgildor
07/06/2021, 7:31 AMgildor
07/06/2021, 7:32 AMBut as I see it doesn’t emit anything, looks that you return nothing thereis a network call to fetch from server and it is working, because iam using that one to store into my sqliteloadProducts
Noushad Chullian
07/06/2021, 7:34 AMgildor
07/06/2021, 7:34 AMgildor
07/06/2021, 7:35 AMNoushad Chullian
07/06/2021, 7:35 AMgildor
07/06/2021, 7:35 AMif (it.isEmpty()) {
emit(State.success(loadProducts()))
} else {
emit(State.success(it))
}
Noushad Chullian
07/06/2021, 7:36 AM// this is how i am calling viewmodel to load
lifecycleScope.launchWhenStarted {
vm.action.emit(ProductListActions.FetchProductList)
}
//the init of viewmodel
init {
viewModelScope.launch { handleIntent() }
}
private suspend fun handleIntent() {
action.collectLatest {
when (it) {
ProductListActions.FetchProductList -> {
getProducts()
}
}
}
Noushad Chullian
07/06/2021, 7:37 AMNoushad Chullian
07/06/2021, 7:37 AMgildor
07/06/2021, 7:39 AMgildor
07/06/2021, 7:39 AMNoushad Chullian
07/06/2021, 7:40 AMgildor
07/06/2021, 7:41 AMgildor
07/06/2021, 7:42 AMflow<State<List<ProductListFromEntity>>> {
to use simple map/catch on flow, it would be more natural code and more flexible and will easily work with flowNoushad Chullian
07/06/2021, 7:44 AMgildor
07/06/2021, 7:45 AMNoushad Chullian
07/06/2021, 7:46 AMgildor
07/06/2021, 7:46 AMNoushad Chullian
07/06/2021, 7:47 AMgildor
07/06/2021, 7:50 AMproductDao::getProducts.toFlow() // convert reference on suspend function to flow, later you can just use any other flow
.map { if (it.isEmpty()) {
loadProducts() // Suppose it returns State
} else {
State.success(it)
}
}
.catch {
emit(State.error(..))
}
Noushad Chullian
07/06/2021, 7:50 AMNoushad Chullian
07/06/2021, 7:51 AMNoushad Chullian
07/06/2021, 7:53 AMprivate suspend fun handleIntent() {
action.collectLatest {
when (it) {
ProductListActions.FetchProductList -> {
getProducts()
}
}
}
this function has another events, but when i am using just collect, it is not collecting from second time, it is working for only first time? any idea about thatgildor
07/06/2021, 8:08 AMgildor
07/06/2021, 8:09 AMNoushad Chullian
07/06/2021, 8:17 AMgildor
07/06/2021, 8:18 AMgildor
07/06/2021, 8:19 AMgildor
07/06/2021, 8:19 AMgildor
07/06/2021, 8:19 AMNoushad Chullian
07/06/2021, 8:22 AMprivate suspend fun handleIntent() {
action.collect {
when (it) {
ProductListActions.FetchProductList -> {
getProducts()
}
}
}
But for the first time the sharedFlow is collected, and not collecting afterwardsgildor
07/06/2021, 8:23 AMNoushad Chullian
07/06/2021, 8:23 AMNoushad Chullian
07/06/2021, 8:24 AMNoushad Chullian
07/06/2021, 8:25 AMprivate suspend fun handleIntent() {
action.collect {
when (it) {
ProductListActions.FetchProductList -> {
getProducts()
}
}
}
But for the first time the sharedFlow is collected, and not collecting afterwardsNoushad Chullian
07/06/2021, 8:27 AMhandleIntent()
is called from the init of the viewModel, So I am thinking the collecting of action inside ths function will persist till the viewModelScope is alive.gildor
07/06/2021, 8:28 AMit is not related to my first questionI understand, and I have even less context, so don’t understand what is going on there
Noushad Chullian
07/06/2021, 8:29 AMgildor
07/06/2021, 8:30 AMNoushad Chullian
07/06/2021, 8:41 AMNoushad Chullian
07/06/2021, 8:41 AMNick Allen
07/06/2021, 8:56 AMNoushad Chullian
07/06/2021, 10:06 AM