ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Retrofit / RxJava] 네트워크 요청 결과를 RxJava로 처리하자 -1-
    개발/Android 2019. 3. 13. 23:00
    반응형

    다음글

    2019/04/04 - [개발/Android] - [Retrofit / RxJava] 네트워크 요청 결과를 RxJava로 처리하자 -2-

    2019/04/06 - [개발/Android] - [Retrofit / RxJava] 네트워크 요청 결과를 RxJava로 처리하자 -3-

    2019/04/09 - [개발/Android] - [Retrofit / RxJava] 네트워크 요청 결과를 RxJava로 처리하자 -4-

     

     Retrofit를 사용할때 RxJava adapter를 추가하여 요청결과를 RxJava의 Observable로 전달받아 원하는 형태로 쉽게 결과값을 후처리 할 수 있도록 구현해 봅시다. 

     

     우선 App의 gradle 설정을 해줍니다.

    android { 
    	...
    
    	dependencies {
    
    		...
    
    		//Retrofit 설정
    		implementation 'com.squareup.retrofit2:retrofit:2.5.0'
    		implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
    		implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
    		//RxJava 설정
    		implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
       		implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
    
    		...
    
    	}
    
    ...
    
    }
    

     

     일단 Retrofit2의 dependecy를 추가해 줍니다. 여기서는 2.5.0 버전을 사용했지만 Retrofit2 배포페이지를 확인해서 최신버전을 확인한 뒤 사용하면 됩니다. 여기에 RxJava를 연결해주기 위해 adapter-rxjava를 추가 합니다. 추가로 Json형태의 결과를 원하는 형태의 class로 변환해줄수 있는 converter-gson도 추가할 수 있습니다. 서버 API의 결과값 형태에 따라서 다른 Converter를 추가하거나 직접 구현할 수 있습니다.

     

     ReactiveX 라이브러리를 사용하기 위해 rxandroid, rxkotlin을 추가합니다. 여기서 kotlin이 아닌 java로 구현하실때는 의존성추가시 rxjava를 추가하시면 됩니다. 마찬가지로 최신버전은 RxAndroid github 페이지, RxKotlin github 페이지, RxJava github 페이지를 참고하여 추가하시면 됩니다.

     

     gradle 설정이 완료되면 Retrofit을 통해 요청할 인터페이스를 정의해 봅시다. 여기서는 테스트를 위해 별도의 authentication token이 필요없는 followers api를 이용하여 테스트를 하도록 하겠습니다.

    interface GithubApi {
        @GET("users/{username}/followers")
        fun getFollowers(@Path("username") username: String): Single<List<GithubUser>>
    }
    
    class GithubUser(
        val login: String,
        val id: Long,
        val node_id: String,
        val avatar_url: String,
        val gravatar_id: String,
        val url: String,
        val html_url: String,
        val followers_url: String,
        val following_url: String,
        val gists_url: String,
        val starred_url: String,
        val subscriptions_url: String,
        val organizations_url: String,
        val repos_url: String,
        val events_url: String,
        val received_events_url: String,
        val type: String,
        val site_admin: Boolean
    )

     get방식으로 api를 요청하며 url에 포함되어야 하는 username은 @path를 통해 parameter로 전달받을 수 있도록 하였습니다. api의 요청 결과는 GithubUser 객체가 리스트 형태로 반환되기 때문에 Single<List<GithubUser>>로 인터페이스의 결과값을 받도록 정의 하였습니다. 

     원래는 Call<T> 형태의 비동기 결과객체를 반환받는데 adapter-rxjava2를 추가하였기 때문에 ReactiveX에서 제공하는 Observable의 한 종류변환하여 반환할 수 있습니다. 여기서는 Single로 받도록 하였습니다.

     

     이제 Retroit을 통해 요청해보도록 합시다. 먼저 Retrofit클래스를 이용하여 GithubApi를 생성합니다.

    class GithubRepository {
        private val githubApi: GithubApi = 
        	createRetrofit("https://api.github.com").create(GithubApi::class.java)
        
    	private fun createRetrofit(baseUrl: String): Retrofit {
    		return Retrofit.Builder()
    			.client(OkHttpClient.Builder()
    				.connectionPool(ConnectionPool(5, 20, TimeUnit.SECONDS))
    				.build())
    			.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    			.addConverterFactory(GsonConverterFactory.create())
    			.baseUrl(baseUrl)
    			.build()
        }
        
        val getFollowers: Single<List<GithubUser>> = githubApi
            .getFollowers("octocat")
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
    }

     Retrofit을 생성시에 CallAdapterFactory와 ConverterFactory를 설정합니다. github api의 결과값이 json이기 때문에 GsonConverterFactory를 설정해주도록 합니다. 

     Android에서는 네트워크 통신시 UI Thread를 이용할 경우 오류가 발생하기 때문에 subscribeOn을 통해 Single의 연산을 처리할 IO Thread를 설정합니다. ReactiveX에서 사용할 수 있는 Scheduler는 여러종류가 있는데 필요와 목적에 따라 구분해서 사용하면 됩니다. (Schedulers 참고)

     subscribe() 메소드를 통해 UI에 전달하기 위해 observeOn()을 통해 AndroidSchedulers.mainThread()를 통해 UI Thread를 설정해 줍니다.

     

     네트워크 동작에 대한 결과값을 보기 위해 간단한 테스트 앱을 이용하여 동작시켜 보도록 합시다. 

    class MainViewModel : BaseViewModel() {
        var repository: GithubRepository? = null
    
    	...
    
        val adapter = GeneralAdapter(GithubUserItemView::class.java)
    
    	...
    
        fun clickRequestFollowers() {
            showProgress.value = true
            addDisposable(repository?.getFollowers?.subscribe(
                { githubUsers ->
                    adapter.setItems(githubUsers)
                    showProgress.value = false
                }, { throwable ->
                    showProgress.value = false
                    showError.value = ErrorMessage("서버요청중에 오류가 발생했습니다.\n${throwable.message}")
                })
            )
        }
    }

     ViewModel에 repository를 설정하고 ViewModel에서 clickevent를 연동합니다. clickRequestFollowers()를 통해 서버요청을 합니다. 요청성공시 adapter에 결과값을 설정합니다 

     기본적인 기능만 사용하여 결과값을 받아오는 형태로 구현하였습니다. 하지만 실제로 서버와 연동을 하는경우에는 좀 더 복잡한 상황이 있을수 있습니다. Http response code를 이용하여 데이터 처리가 바뀐다거나, 재시도를 몇회 한다거나 하는 등의 추가 스펙이 있을수 있습니다.

     다음은 좀 더 세부적으로 제어할 수 있도록 기능을 추가해 보도록 하겠습니다.

    반응형
Designed by Tistory.