안드로이드

RxJava2을 사용한 Retrofit통신

코딩하는후운 2022. 11. 4. 16:13
반응형

1. 5개의 파일을 만듭니다(ApiProvider, MyApi, MyModel, MyModelItem, MainActivity)

1) ApiProvider.kt

fun provideMyApi(): MyApi
  = Retrofit.Builder()
    //통신할 서버의 주소를 입력합니다.
    .baseUrl("http://www.example.com")
    //네트워크 요청 로그를 표시해 줍니다.
    .client(provideOkHttpClient(provideLoggingInterceptor()))
    //받은 응답을 옵저버블 형태로 변환해 줍니다.
    .addCallAdapterFactofy(RxJava2CallAdapterFactory.createAsync())
    //서버에서 json 형식으로 데이터를 보내고 이를 파싱해서 받아옵니다.
    .addConverterFactory(GsonConverterFactory.create())
    .build()
    .create(MyApi::class.java)




2)네트워크 통신에 사용할 클라이언트 객체를 생성합니다.

private fun provideOkHttpClient(interceptor: HttpLoggingInterceptor): OkHttpClient{
  val b = OkHttpClient.Builder()
  //이 클라이언트를 통해 오고 가는 네트워크 요청/응답을 로그로 표시하도록 합니다.
  b.addInterceptor(interceptor)
  return b.build()
}

//네트워크 요청/응답을 로그에 표시하는 Interceptor 객체를 생성합니다.
private fun provideLoggingInterceptor(): HttpLoggingInterceptor{
  val interceptor = HttpLoggingInterceptor()
  interceptor.level = HttpLoggingInterceptor.Level.BODY
  return interceptor
}




2) MyApi

interface MyApi{
  /**
  * POST -> POST 통신할 주소를 입력합니다.
  * Field -> POST 통신을 위한 파라미터를 입력합니다.
  * Return 값은 Observable<MyModel> 형태로 되어 있지만
  * Model이 없는 경우 Observable<Any>로 적으시면 됩니다.
  */
  @FormUrlEncoded
  @POST("/example/post/address")
  fun postGetMyExample(@Field("field1") field1: String,
                        @Field("field2") field2: String): Observable<MyModel>
}



3) MyModel

class MyModel(val result: Boolean, val description: String, val data: MyModelItem)



3-1)MyModelItem

class MyModelItem(@field: SerializedName("param_1") val param1: String,
                  @field: SerializedName("param_2") val param2: String,
                  @field: SerializedName("param_3") val param3: String,)


위 Model은 만약 아래와 같은 데이터가 올 경우 받기 위한 형식입니다.
(model class 변수명과 서버 데이터의 변수명이 다를 경우 @field: SerializedName 어노테이션을 통해 일치 시켜줄수 있습니다.)

4) MainActivity

private val api by lazy { provideMyApi()}
private val disposable = CompositeDisposable()


disposable.add(api.postGetMyExample("인자_1", "인자_2")
        //REST API를 통해 받은 응답에서 Result값을 추출합니다.
        .flatMap{
          if(it.result){
            //결과를 다음 스트림으로 전달합니다.
            Observable.just(it.data)
          }else{
            //검색 결과 false
            //에러를 발생시켜 에러 메시지를 표시하도록 합니다.
            //곧바로 에러 블록이 실행됩니다.
            Observable.error(IllegalStateException("retusn result is false"))
          }
        }
        //이 이후에 수행되는 코드는 모두 메인 스레드에서 실행합니다.
        .observeOn(AndroidSchedulers.mainThread())
        //구독할 때 수행할 작업을 구현합니다.
        .doOnSubscribe{}
        //스트림이 종료될 때 수행할 작업을 구현합니다.
        .doOnTerminate{}
        //옵저버블을 구독합니다.
        .subscribe({ data ->
          //data 를 받아 처리합니다.
          //작업중 오류가 발생하면 이 블록은 호출되지 않습니다.

        }){
          //에러 블록
          // 네트워크 오류나 데이터 처리 오류 등
          // 작업이 정상적으로 완료되지 않았을 때 호출됩니다.

        })




===Retrofit을 Rx식으로 사용ㅎ면 여러 에러를 미연에 방지할 수 있습니다.
1.Model의 인자와 변수명이 다르거나 없어도 앱이 죽지 않습니다.
class MyModel(val result: Boolean, val description: String, val data: MyModelItem)
예를 들어 result의 변수명은 Boolean이지만 서버로부터 String형식으로 오거나 데이터가 없어도 Rx식은

에러 블록으로 이동 되고 앱이 Crash되지 않습니다.

2. Retrofit 통신에서 UI를 변화 시키는 도중 Activity가 사라지면서 발생하는 에러를 막을 수 있습니다.

override fun OnDestroy(){
  //Activity가 종료 되면
  //사용중인 통신을 중단합니다.
  disposable.clear()
}



3. Rx식을 사용하면 가독성이 좋아 코드의 유지 보수가 편해집니다.

 

 

 

참조 :

https://black-jin0427.tistory.com/34?category=727620 

 

[Android, Retrofit, RxJava2] RxJava2 을 사용한 Retrofit 통신

안녕하세요. 블랙진입니다. 안드로이드 통신을 하는데 Retrofit 을 많이 사용합니다. 아래는 Retrofit 에 대한 문서입니다. - 한글 http://devflow.github.io/retrofit-kr/ - 영어 https://square.github.io/retr..

black-jin0427.tistory.com

 

반응형