일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- r
- 추상팩토리패턴
- 프로토타입 패턴
- ㅓ
- 디자인패턴
- a
- 옵저버 패턴
- Functional Programming
- El
- 디자인패턴 #
- designPattern
- Kotlin
- ㅋㅁ
- 싱글톤
- PrototypePattern
- Observer Pattern
- F
- builderPattern
- 함수형프로그래밍
- Design Pattern
- 코틀린
- 빌터패턴
- Singleton
- 팩토리 메소드
- Abstract Factory
- 추상 팩토리
- factory method
- Today
- Total
오늘도 더 나은 코드를 작성하였습니까?
단일값을 보내는 flow 와 flow의 결합. 본문
단일값을 보내는 flow
// plantsListSortOrderCache.getOrAwait()는 flow<List<Plant>> 반환.
private val customSortFlow = flow { emit(plantsListSortOrderCache.getOrAwait()) }
// Create a flow that calls a single function
private val customSortFlow = plantsListSortOrderCache::getOrAwait.asFlow()
getOrAwait를 호출하고 결과를 첫 번째이자 유일한 값으로 내보내는 새 Flow를 만듭니다.
::을 사용하여 결과 Function 객체에서 asFlow를 호출하는 getOrAwait 메서드를 참조하면 됩니다.
두 코드는 모두 동일한 작업을 합니다. getOrAwait를 호출하고 결과를 내보낸 후 완료합니다
두 flow의 결합시키기
// retrofit.kt
interface SunflowerService {
@GET("googlecodelabs/kotlin-coroutines/master/advanced-coroutines-codelab/sunflower/src/main/assets/plants.json")
suspend fun getAllPlants() : List<Plant>
@GET("googlecodelabs/kotlin-coroutines/master/advanced-coroutines-codelab/sunflower/src/main/assets/custom_plant_sort_order.json")
suspend fun getCustomPlantSortOrder() : List<Plant>
}
suspend fun customPlantSortOrder(): List<String> = withContext(Dispatchers.Default) {
val result = sunflowerService.getCustomPlantSortOrder()
result.map { plant -> plant.plantId }
}
// repository.kt
private val customSortFlow = plantService::customPlantSortOrder().asFlow()
// customSortFlow 결과가 나오면 위의 flow 의 값( plantDao.getPlantsFlow())에 최신 값과 결합합니다
// 따라서 두 'plants' 와 `sortOrder`는 초기 값 (flow 가 하나 이상의 값을 내보냈다면)이 있다면,
// 모든 변경사항이 `plants` 또는`sortOrder`는 `plants.applySort (sortOrder)를 호출한다.
val plantsFlow: Flow<List<Plant>>
get() = plantDao.getPlantsFlow()
.combine(customSortFlow) { plants, sortOrder ->
// plants 는 데이터베이스에서 가져오고
// 정렬순서는 네트워크 통신을 통해 받아온다.
plants.applySort(sortOrder)
}
combine 연산자는 두 flow을 결합합니다.
두 flow 모두 자체 코루틴에서 실행되고, 각 flow에서 새 값이 생성될 때마다 각 흐름의 최신 값으로 변환이 호출됩니다.
combine을 사용하면 캐시된 네트워크 조회를 데이터베이스 쿼리와 결합할 수 있습니다.
두 가지 모두 서로 다른 코루틴에서 동시에 실행됩니다. 즉, 데이터베이스에서 qurey 요청을 시작하는 동안 Retrofit에서 네트워크 쿼리를 시작할 수 있습니다. 그런 다음 두 flow 모두에서 결과가 나오는 즉시 combine 람다를 호출하여 로드된 식물에 로드된 정렬 순서를 적용합니다.
combine 변환은 결합되는 flow별로 코루틴을 하나씩 실행합니다. 따라서 두 흐름을 동시에 결합할 수 있습니다.
flow을 '공정한' 방식으로 결합합니다. 즉, 하나의 flow가 tight loop(CPU 및 IO처리를 많이 반복하는)에서 생성되더라도 모두 값을 생성할 기회가 있습니다.
combine 연산자의 작동 방식을 살펴보기.
onStart에 상당한 지연을 포함하여 두 번 내보내도록 다음과 같이 customSortFlow를 수정합니다.
private val customSortFlow = plantsListSortOrderCache::getOrAwait.asFlow()
.onStart {
// 먼저 빈 리스트 내보냄.
emit(listOf())
// 5초 지연.
delay(5000)
}
onStart - transform은 관찰자가 다른 연산자 이전에 값을 수신하면 발생합니다. placeholder values를 내보낼 수 있습니다.
위 코드는 빈 목록을 내보내고 getOrAwait 호출을 1,500밀리초 지연한 후에 원래 흐름을 계속합니다.
지금 앱을 실행하면 Room 데이터베이스 쿼리가 즉시 반환되어 빈 목록과 결합됩니다(알파벳순으로 정렬됨).
그런 다음 약 5000밀리초 후에 맞춤 정렬이 적용됩니다.
onStart를 사용하여 flow이 실행되기 전에 suspend 코드를 실행할 수 있습니다. flow에 추가 값을 내보낼 수도 있으므로이를 사용하여 네트워크 요청 흐름에서 Loading 상태를 내보낼 수 있습니다.
'Coroutine > coroutineFlow' 카테고리의 다른 글
Flow를 사용한 동시 실행 제어 (0) | 2021.05.31 |
---|---|
Flow를 사용한 스타일 혼합 (0) | 2021.05.31 |
flow을 사용한 비동기 작업 (0) | 2021.05.31 |
flow의 실행 방법 (0) | 2021.05.31 |
stateFlow sharedFlow (0) | 2021.05.27 |