Kotlin Flow

TRASALBY·2024년 3월 19일
0

학습내용 옮기기

목록 보기
6/8
post-thumbnail

Flow

코루틴 상에서 리액티브 프로그래밍을 지원하기 위한 구성요소

리액티브 프로그래밍

데이터가 변경될 때 이벤트를 발생 시켜 데이터를 계속 전달하도록 하는 프로그래밍 방식

  • 기존의 명령형 프로그래밍에서 데이터의 소비자는 데이터를 요청한 후 받은 결과를 일회성으로 수신한다.
  • 이러한 방식은 데이터가 필요할 때마다 결과값을 매번 요청해야 하기에 매우 비효율 적이다.
    • 리액티브 프로그래밍에서는 데이터를 발행하는 발행자가 있고 데이터의 소비자는 발행자에게 구독 요청을 한다.
    • 발행자는 새로운 데이터가 들어오면 데이터의 소비자에게 지속적으로 발행한다.

🍀 리액티브 프로그래밍에서 하나의 데이터를 발행하는 발행자가 있고 발행자는 데이터의 소비자에게 지속적으로 데이터를 전달하는 역할을 하는데 이를 데이터 스트림 이라고 한다.

Coroutine Flow를 사용한 리액티브 프로그래밍

Coroutine Flow는 코루틴 상에서 리액티브 프로그래밍을 지원하기 위해 만들어진 구현체이다.

데이터 스트림의 구성 요소

  • Producer(생산자)
  • Intermediary(중간 연산자)
  • Consumer(소비자)

미세먼지 앱을 만든다고 가정하면 다음과 같은 과정을 거친다.

  1. Flow { } 블록을 선언
  2. 미세먼지 데이터를 서버로 부터 받아옴. (Remote DataSource)
  3. Producer가 데이터를 생성 (emit)
  4. 2~3의 과정을 60초마다 반복하여 데이터를 계속 생성
class DustRemoteDataSource(
    private val dustApi: DustApi
) {
    fun getDustInfoFlow() : Flow<List<DustInfo>> = flow { // 1.Flow 블록 선언
        while (true) {
            val dustInfos = dustApi.fetchLastedDustInfo() //2. 데이터 받아오기
            emit(dustInfos) //3. Producer가 데이터 발행
            delay(INTERVAL_REFRESH) //4. 60초마다 반복
        }
    }

    companion object {
        private const val INTERVAL_REFRESH: Long = 60000
    }
}

Producer (생산자)

생산자는 데이터를 발행시키는 역할을 한다.

Flow에서의 Producer는 flow { }블록 내에서 emit을 통해 데이터를 생성한다.

Intermediary(중간 연산자)

생성된 데이터를 수정하는 역할을 한다.

map(데이터 변형), filter(데이터 필터링), onEach(모든 데이터마다 연산 수행) 등의 중간 연산자가 있다.

예를 들어 앞선 미세먼지 어플에서 모든 지역의 미세먼지 데이터는 불 필요하다. 내 지역의 미세먼지 데이터만을 구하기 위해 아래와 같이 사용할 수 있다.

class DustRepository(
	private val dustRemoteDataSource: DustRemoteDataSource,
) {
		fun getDustsInfoOfViewItem(local: Locale) = 
			dustRemoteDataSource.getDustInfoFlow().map{it.filter{this.locale == locale}}
}

Consumer(소비자)

중간 연산자를 통해 수정된 데이터를 소비자에게 전달 한다.

Flow에서는 collect를 이용해 전달된 데이터를 소비할 수 있다.

안드로이드 상에서 데이터의 소비자는 보통 UI 구성요소 이다. UI는 데이터를 소비하여 데이터에 맞는 UI를 그리게 된다.

class DustViewModel(
    private val dustRepository: DustRepository
) : ViewModel() {
    fun collectDustInfoOf(locale: Locale) = 
        viewModelScope.launch {
            dustRepository.getDustInfoOf(locale).collect { dustInfos ->
                // TODO
            }
        }
    }
}

0개의 댓글

관련 채용 정보