Why will the emitting data in transform disappear in Kotlin?

Viewed 30

I use transform to emit both Result.Loading and Result.Success(listEntityToModel(it)) in Code A , and use val myResult by mViewMode.listRecord().collectAsState(initial =Result.Error(Exception()) ) to collect data.

I find the Result.Loading disappear when I use Code A.

But if I use Code B, I can Result.Loading when I use collect.

What's wrong with Code A ?

Code A

override fun listRecord(): Flow<Result<List<MRecord>>> {
        return mRecordDao.listRecord().transform  {
            emit(Result.Loading)   //It disappear when colloect
            emit( Result.Success(listEntityToModel(it)) )
        }
}



sealed class Result<out R> {
    data class Success<out T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
    object Loading : Result<Nothing>()
}


val myResult by mViewMode.listRecord().collectAsState(initial =Result.Error(Exception()) )

Code B

override fun listRecord(): Flow<Result<List<MRecord>>> {
   return   flow {
      emit(Result.Loading)  //I can get it when collect
      val s=mRecordDao.listRecord().map { Result.Success(listEntityToModel(it)) }
      emitAll(s)
   }       
}

//The same
1 Answers

In Code A, you are transforming the parent flow, so inside the transform function, the first result from the parent flow has already arrived. It will emit "loading" and then emit the result immediately afterwards because the result is already available. The collector will process both one after the other on the same thread, so there will be no opportunity for the UI to show the first value.

In Code B, you emit "loading" before you even begin to collect from the other flow, so it will be a little while before that first result from the other flow arrives. It has to do some database query to get the first result.

Related