Flow

BongKu·2023년 7월 31일
0

Android

목록 보기
17/30
post-thumbnail

Flow 란 코루틴에서 단일 값만 반환하는 Suspend fun 과 달리 여러 값을 순차적으로 내보낼 수 있는 유형입니다.

기본적으로 코루틴 기반으로 동작하며, 데이터베이스 조회, 파일 입출력 등과 같은 비동기 작업을 처리할 때 Flow를 사용하면 콜백 헬을 피하고 코드의 가독성과 유지보수성을 높일 수 있습니다.

Flow에서 사용하는 주요 함수는 다음과 같습니다.

emit: Flow를 생성하거나 중간 연산자에서 값을 내보낼 때 사용하는 함수입니다. emit 함수를 호출하여 값을 Flow로 내보내면, Flow를 수집하는 코루틴이 해당 값을 받게 됩니다.
flow: Flow를 생성하기 위한 빌더 함수입니다. flow 빌더 함수 내에서 emit 함수를 사용하여 값을 Flow로 내보낼 수 있습니다.
collect: Flow를 수집하는 함수로, 값을 기다리고 받을 때까지 현재 코루틴을 일시 정지시킵니다. collect 함수를 사용하여 Flow에서 값을 받으면서 해당 값을 처리할 수 있습니다.
map: Flow의 값을 변형하기 위한 중간 연산자입니다. 각 요소를 변형하여 새로운 Flow를 반환합니다.
filter: Flow의 값을 필터링하기 위한 중간 연산자로, 주어진 조건에 맞는 요소만 포함된 새로운 Flow를 반환합니다.
onEach: Flow의 각 요소에 대해 추가 작업을 수행하기 위한 중간 연산자입니다. 주로 로깅 또는 부가적인 작업에 사용됩니다.
catch: Flow에서 예외 처리를 하기 위한 중간 연산자입니다. 예외가 발생할 경우 처리할 작업을 정의할 수 있습니다.
flowOn: Flow의 상위 스트림에서 CoroutineContext를 변경하기 위한 중간 연산자입니다. Flow의 값을 emit하는 CoroutineContext를 변경하고자 할 때 사용됩니다.
flattenConcat: 여러 개의 Flow를 연결하여 순차적으로 처리하는 함수입니다. 첫 번째 Flow가 완료된 후에 두 번째 Flow를 처리합니다.
flattenMerge: 여러 개의 Flow를 병합하여 동시에 처리하는 함수입니다. 모든 Flow를 동시에 처리하며, 결과를 수집하는 Flow를 반환합니다.
combine: 두 개의 Flow를 결합하여 새로운 값을 생성하는 함수입니다. 각 Flow가 값을 내보낼 때마다 조합 함수를 사용하여 결과를 생성합니다.
zip: 두 개의 Flow를 병렬로 결합하는 함수입니다. 각 Flow가 동일한 인덱스의 요소를 가지고 있을 때, 조합 함수를 사용하여 결과를 생성합니다.

예제

사용자 목록을 불러오는 간단한 예제를 보도록 하겠습니다.

class UserRepository {
    private val apiService = ApiService()

    // Flow를 사용하여 사용자 이름 목록을 가져오는 함수
    fun getUserNames(): Flow<List<String>> = flow {
        // 네트워크 요청을 비동기적으로 실행
        val names = apiService.fetchUserNames()
        emit(names) // 사용자 이름 목록을 Flow로 내보냄
    }
}

네트워크 요청을 비동기적으로 실행하는 fetchuserNames를 호출하고, 해당 요청의 결과로 얻은 사용자 이름 목록을 emit 하여 Flow로 보냅니다.

class UserViewModel : ViewModel() {
    private val userRepository = UserRepository()

    // 사용자 이름 목록을 담을 MutableLiveData
    private val _userNames = MutableLiveData<List<String>>()
    val userNames: LiveData<List<String>>
        get() = _userNames

    // Flow를 수집하여 사용자 이름 목록 업데이트
    fun fetchUserNames() {
        viewModelScope.launch {
            userRepository.getUserNames()
                .collect { names ->
                    _userNames.value = names
                }
        }
    }
}

collect 를 사용해서 Flow에 있는 사용자 목록을 수집합니다.

class MainActivity : AppCompatActivity() {
    private lateinit var userViewModel: UserViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        userViewModel = ViewModelProvider(this).get(UserViewModel::class.java)

        // 사용자 이름 목록의 LiveData를 관찰하여 UI 업데이트
        userViewModel.userNames.observe(this, Observer { names ->
            // UI 업데이트 코드
            // names를 사용하여 RecyclerView 등에 사용자 이름 목록을 표시
        })

        // 사용자 이름 목록 가져오기 요청
        userViewModel.fetchUserNames()
    }
}

UserRepository에서 Flow를 생성하여 네트워크 요청을 비동기적으로 실행하고, 결과를 Flow로 내보내며, viewModel에서 해당 Flow에 있는 정보를 비동기적으로 수집합니다. Flow의 값이 업데이트 되면 LiveData에 의해 MainActivity의 UI가 업데이트 됩니다.

참고
https://developer.android.com/kotlin/flow?hl=ko

profile
화이팅

0개의 댓글