본문 바로가기

Android

[Android] Naver검색 api - RxJava, Retrofit, MVVM, Hilt

 

ReactiveX는 비동기 프로그래밍 그리고 Observable 시퀀스를 이용해 이벤트를 처리하기 위한 라이브러리이다.

 

이 라이브러리는 Observer Pattern을 사용한다.

필요로 하는 데이터들을 요청하여 받아오는 방식이 아닌,

데이터가 변경되면 요청을 받겠다는 구독신청을 해놓고 변경사항이 발생하면 전달 받는 방식이다.

 

Observable은 onNext, onError, onComplete 세가지 알림을 구독자에게 전달한다.

1) onNext : Observable이 데이터 발행을 알림

2) onError : error가 발생했을을 알리고 Observable을 종료

3) onComplete : 모든 이벤트가 발행을 완료했음을 알림

 

RxJava2부터는 ObservableSingle 클래스 이외에도 Maybe, Flowable 클래스를 제공한다. 더 공부해보고 상황에 맞게 잘 사용하자.

(Single은 Observable의 한 형태로 데이터를 무한하게 발행할 수 있는 Observable과는 반대로 오직 1개의 데이터만 발행한다.)

 

Scheduler는 다중 프로그래밍을 가능하게 하는 운영체제의 동작 기법이다. RxAndroid에서는 Scheduler를 지정하기 위해 2가지를 사용한다.

1) SubscribeOn: Observable연산을 사용하기 위해 처음 사용할 Thread를 지정한다.

2) ObservableOn: SubscribeOn된 스레드를 Observable의 체인 이후에 사용할 Thread를 변경할 때 사용된다.

 

실제로 지정할 Scheduler에는 

 

1) Schedulers.io() - 동기 I/O를 별도로 처리시켜 비동기 효율을 얻기 위한 스케줄러

2) Schedulers.immediate() - 현재 스레드에서 즉시 실행

3) Schedulers.newThread() - 새로운 스레드를 만드는 스케쥴러

4) AndroidSchedulers.mainThread() - 안드로이드의 UI스레드에서 수행하는 스케쥴러

 

이외에도 여러가지가 있다!!!

 

네이버 영화 검색 api로 연습을 해보았다.

 

우선 RetrofitClient를 생성할 때 RxJavaConverterFactory를 추가해준다.

    @Provides
    @Singleton
    fun provideRetrofit(okHttpClient: OkHttpClient, NAVER_API_URL: String): Retrofit {
        return Retrofit.Builder()
            .baseUrl(NAVER_API_URL)
            .client(okHttpClient)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .build()
    }

 

기존에 우리는 Retrofit 응답 객체를 Call이나 Response로 선언을 해주었지만,

Observable로 바꿔준다. Observabler을 통해서 MovieResponseModel을 발행해준다고 생각하면 된다.

interface SearchMovieService {
    @GET("/v1/search/movie.json")
    fun getMovieList(@Query("query") query: String): Observable<MovieResponseModel>
}

 

이후 Repositroy구현도 일반적인 패턴으로 작성해준다.

class SearchMovieRepository @Inject constructor(
    val searchMovieService: SearchMovieService
) {
    fun getMovieList(query: String): Observable<MovieResponseModel> =
        searchMovieService.getMovieList(query)
}

 

 

뷰모델에서는 Repository를 주입받고 getMovieList()라는 함수를 통해 받아온 데이터에 구독을 신청해준다.

그 작업이 subscribeOn에서 Scheduler를 지정하는 것이다.

Http통신 작업을 하기 위해 스케쥴러는 Scheduler.io()로 지정해준다.

observeOn()은 이후에 우리가 데이터를 주워서 사용하기 위한 Thread를 지정해주는 것이다.

adapter를 통해 Recyclerview에 뿌려주는 UI작업을 할 예정이기 때문에 Main Thread로 지정해준다.

class SearchMovieViewModel @ViewModelInject constructor(
    val searchMovieRepository: SearchMovieRepository
) : BaseViewModel() {

    private val _movieList = MutableLiveData<MovieResponseModel>()
    val movieList: LiveData<MovieResponseModel>
        get() = _movieList

    val searchQuery: MutableLiveData<String> = MutableLiveData<String>()


    fun getMovieList() {
        searchMovieRepository.getMovieList(
            searchQuery.value!!
        ).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({
                _movieList.postValue(it)
                Log.e("update movie list", movieList.value.toString())
            }, {
                Log.e("error :", it.stackTraceToString())
            })
    }
}