Android/Coroutine

Android Coroutine Flow - 2 (실제로 써보기)

최데브 2022. 2. 11. 12:45

이론으로만 알고 있는것과 직접 써보는건 많이 차이가 난다.

간단한 깃허브 api 호출 예제로 flow를 사용해보자.

 

설명에 앞서 해당 예제는 MVVM 패턴으로 구성 되었다.

hilt , retrofit2 등 라이브러리를 사용했지만 해당 라이브러리에 대한 사용법은 따로 적지 않겠다.

 

이해를 편하게 하기 위해 생성자 - 중간연산자 - 소비자 순서로 코드 설명을 진행하겠다.

 

먼저 생성자다.

 

interface GitModel {
    suspend fun getRepos(owner: String) : List<GithubRepo>
}
interface RetroServiceInstance {
    @GET("users/{owner}/repos")
    suspend fun getRepos(@Path("owner") owner: String) :List<GithubRepo>
}
@Singleton
class GitModelImple  @Inject constructor (private val serviceInstance: RetroServiceInstance) : GitModel{


    override suspend fun getRepos(owner: String): List<GithubRepo> {
        return serviceInstance.getRepos(owner)
    }

}

retrofit2 을 이용해서 github에서 repo 정보를 가져온다. 

데이터를 가져오는 부분이 되겠다.  

 

그리고 가져온 부분을 viewmodel 에서 처리한다.

@HiltViewModel
class MainViewModel @Inject constructor( val client : GitModelImple) : ViewModel() {

    private val _gitHubData =  MutableSharedFlow<List<GithubRepo>>()
    val gitHubData = _gitHubData.asSharedFlow()

    fun getGitHubData(owner : String){
       val job =  viewModelScope.async {
           client.getRepos(owner) //서버와 통신하기 때문에 네트워크 시간이 필요하므로
           //async 를 사용
        }

        viewModelScope.launch {
            var data = job.await().asFlow().filter { //await로 통신이 완료되면 받아오고 
                it.name[0] == 'A' //filter 를 사용해서 repo의 이름이 A 로 시작되는것만 list 로 만든다
            }// 이 과정이 중간연산자가 된다.
            _gitHubData.emit(data.toList())
        }
    }

}

전체적인 설명은 주석으로 대체하겠다. 

사실 repository 를 만들어서 거기서 중간연산자 처리를 하고 viewmodel 로 가져오는 단계를 거치는게 더 깔끔하고 관리하기도 편하지만 이번에는 그냥 viewmodel 에서 처리했다. 

 

마지막으로 소비자쪽 코드를 보자

 

@AndroidEntryPoint
class MainActivity : BaseActivity<ActivityMainBinding>() {

    override val layoutResourceId: Int
        get() = R.layout.activity_main

    private val viewModel: MainViewModel by viewModels()


    override fun initStartView() {
        viewModel.getGitHubData("supremehyo")
    }

    override fun initDataBinding() {

        val scope = CoroutineScope(Dispatchers.IO)
        scope.launch {
            viewModel.gitHubData.collect {
                    it.forEach {
                        Log.v("gitData" , it.name)
                    }
            }
        }
    }

    override fun initAfterBinding() {

    }


}

collect 를 사용해서 Log에 A로 시작하는 repo의 이름들만 출력되는걸 확인 할 수 있다.

 

 

반응형