emit
등을 이용해 flow builder 생성CoroutineContext
에서 실행 flowOn
modifier 사용하여 upstream flow 변경 가능map
, filter
등 사용flowOn
modifier 사용하여 upstream flow 변경 가능collect
연산자 사용하여 데이터 수집interface NewsApi {
@GET("/api/news")
suspend fun fetchLatestNews(): List<ArticleHeadline>
}
interface NewsRemoteDataSource {
suspend fun fetchLatestNews(): Flow<List<ArticleHeadline>>
}
class NewsRemoteDataSourceImpl(
private val newsApi: NewsApi,
private val refreshIntervalMs: Long = 5000,
private val ioDispatcher: CoroutineDispatcher
) : NewsRemoteDataSource {
override fun fetchLatestNews(): Flow<List<ArticleHeadline>> = flow {
while(true) {
val latestNews = newsApi.fetchLatestNews()
emit(latestNews) // 결과 flow로 emit
delay(refreshIntervalMs) // 반복 요청 주기
}
}
// data layer에서 I/O 작업 수행하므로
.flowOn(ioDispatcher)
}
class NewsRepository(
private val newsRemoteDataSource: NewsRemoteDataSource,
private val userData: UserData,
private val defaultDispatcher: CoroutineDispatcher
) {
val favoriteLatestNews: Flow<List<ArticleHeadline>> =
newsRemoteDataSource.fetchLatestNews()
.map { news ->
news.filter { userData.isFavoriteTopic(it) }
}
.onEach { news ->
saveInCache(news)
}
// flowOn 위쪽 stream은 defaultDispatcher에서 실행
.flowOn(defaultDispatcher)
// flowOn 아래쪽 stream은 consumer's context에서 실행
.catch { exception -> // Executes in the consumer's context
emit(lastCachedNews())
}
}
class LatestNewsViewModel(
private val newsRepository: NewsRepository
) : ViewModel() {
init {
viewModelScope.launch {
// 데이터 수집 시작
newsRepository.favoriteLatestNews.collect { favoriteNews ->
// 이제 view를 위한 작업 진행
}
}
}
}
https://developer.android.com/kotlin/flow
https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/