I am new with kotlin flow and I am working about this document. Kotlin Flows. In this code every five seconds datasource fetch data from api and emits it.
This is my example datasource class.
I am getting data and emitting it.
class RemoteDataSourceImpl @Inject constructor(
private val api:CryptoApi
): RemoteDataSource {
override suspend fun cryptoList(): Flow<List<CryptoCoinDto>> {
return flow {
while (true){
val data = api.getCoinList()
emit(data)
delay(5000L)
}
}
}
}
This is my example repository.
I am mapping data and saving it room database. I want to get data from room database and emit it because of single source of truth principle but I still have to return dataSource because if I open new flow{} I can't reach datasource's data. Of course I can fix the problem by using List instead of Flow<List> inside of RemoteDataSource class. But I want to understand this example. How can I apply here single source of truth.
class CoinRepositoryImpl @Inject constructor(
private val dataSource:RemoteDataSource,
private val dao: CryptoDao
):CoinRepository {
override fun getDataList(): Flow<List<CryptoCoin>> {
dataSource.cryptoList().map { dtoList ->
val entityList = dtoList.map { dto ->
dto.toCryptoEntity()
}
dao.insertAll(entityList)
}
return dataSource.cryptoList().map {
it.map { it.toCryptoCoin() }
}
}
Maybe this can help. I personally wouldn't return a Flow for the API stuff since you are technically speaking returning only 1 list all the time
override fun getDataList(): Flow<List<CryptoCoin>> {
val localFlow = dao.getCryptoCoins()
val apiFlow = flow<Unit> {
// Since getDataList can't be suspend due to it returning a flow, we create a new flow simply to run a suspendable function
getAndSaveCryptoCoinsFromApi()
}.onStart { // If I don't add this onStart, then it won't work
emit(Unit)
}
return localFlow.combine(apiFlow) { dbItems, _ ->
dbItems
// We just return DB items. Why? Since we are saving api items to the db, and since the db items return a flow, it will automatically emit values to the flow once new items are added to the db
}
}
private suspend fun getAndSaveCryptoCoinsFromApi() {
try {
val result = api.getCryptoCoins().toDomain()
val entities = result.map { it.toEntity() }
dao.insertCoins(entities)
} catch(e: Exception) { /**/ }
}