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
'안드로이드' 카테고리의 다른 글
STT(구글) - SpeechRecognizer Document (0) | 2022.11.09 |
---|---|
STT(Speech-to-Text)란? (0) | 2022.11.09 |
[Android] DB Realm Migration (0) | 2022.11.04 |
[Android] Lottie 애니메이션 (0) | 2022.11.04 |
[Android] Di(Dependency Injection) Koin에 대해 알아보자 (0) | 2022.11.04 |