Notice
Recent Posts
Recent Comments
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
관리 메뉴

코린이 탈출기

[RxJava] Giphy API를 활용한 gif 추천 애플리케이션 본문

Android 공부

[RxJava] Giphy API를 활용한 gif 추천 애플리케이션

명란파스타 2021. 12. 21. 00:05

이번 RxJava 스터디에서 토이 프로젝트로 Giphy API를 이용해서 gif 추천/검색 등 다양한 기능을 하는 앱을 만들어보려고 한다.

RxJava를 익히기 위해서 만들어보는 거라서 아주 잡다한 기능이 많이 추가될 예정 ..

 

Giphy API는 RESTful API로, 여러가지 gif들을 api 형식으로 제공해주고 있다. https://developers.giphy.com/docs/api/endpoint/#trending 해당 문서를 참고하면 된당

 

먼저 사용해볼 api는 random api! 말그대로 랜덤으로 gif를 반환해준다. 이 api로 우선은 랜덤으로 10개의 gif를 받아와서 recyclerView를 통해 띄워보도록 하쟈

 

프로젝트 구성

  • data: gif data 클래스 패키지
  • di: dagger2로 의존성 주입을 하기 위해 필요한 component, module을 모아둔 패키지
  • network: GiphyApi, GiphyApiClient, GiphyRandomResponse
  • ui: ui 작업에 필요한 클래스들

Dagger2를 통해서 의존성 주입을 해둔 상태인데, 해당 부분은 따로 포스팅을 해야겠다.

사실 아직 나도 개념이 정확하게 잡힌 건 아닌 것 같아서 블로그에 쓰면서 좀 더 확실하게 공부를 해야한다 .. 너무 어려운 대거 😂

 

Retrofit과 RxJava 사용하기

- Retrofit을 통해 요청할 인터페이스 생성

get 방식으로 API를 요청하여 받은 결과는 GiphyRandomResponse 형식으로 반환받을 수 있도록 한다. 원래는 Call<T> 형태의 비동기 결과 객체를 반환하지만, Retrofit Builder에서 addCallAdapterFactory 메소드를 통해서 RxJava에서 사용되는 observables 객체를 반환할 수 있도록 해준다. 여러 observables 중 나는 Single을 사용했다.

interface GiphyApi {
    @GET("/v1/gifs/random")
    fun getRandomGif(
        @Query("api_key") apiKey: String,
        @Query("tag") tag: String?,
        @Query("rating") rating: String?,
        @Query("random_id") randomId: String?
    ): Single<GiphyRandomResponse>
}
class GiphyApiClient @Inject constructor (
    private val giphyApi: GiphyApi
) {
    fun getRandomGiphy(): Single<GiphyRandomResponse> {
        return giphyApi.getRandomGif(Constants.apiKey, null, null, null)
    }
}

- Retrofit 객체 생성 in App Module

Retrofit과 GiphyApi 객체는 application 수준에서 하나만 생성되면 된다. 따라서, AppModule 클래스에서 해당 객체들을 provides 할 수 있도록 한다.

@Module
class AppModule(private val application: Application) {
    val gson = GsonBuilder()
        .setLenient()
        .create()

    @Provides
    fun application() = application

    @Provides
    fun retrofit() = Retrofit.Builder()
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // rxjava를 사용가능
        .addConverterFactory(GsonConverterFactory.create())
        .baseUrl(Constants.baseUrl)
        .build()

    @Provides
    fun giphyApi(retrofit: Retrofit) =
        retrofit.create(GiphyApi::class.java)
}

 

- API 요청 및 결과 데이터 받기

fun getRandomGiphy() {
    giphyApiClient.getRandomGiphy()
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .doOnSuccess { response ->
            _randomGiphy.postValue(response.data)
            if (giphyCount < maxCount) {
                giphyCount += 1
                getRandomGiphy()
            }
        }
        .doOnError {
            Log.e(TAG, "getRandomGiphy error: response is not successful or response.body is null")
        }
        .subscribe()
 }

해당 함수는 GiphyListViewModel에 구현하였다. constructor injection으로 giphyApiClient를 주입해주고 있다. 

.subscribeOn(Schedulers.io()): io 스레드에서 데이터를 받아온다

.observeOn(AndroidSchedulers.mainThread()): 응답값을 가지고 ui 업데이트를 하기 위해. ui 업데이트는 오로지 main thread에서만 가능하다.

.doOnSuccess{}: 데이터를 받아오는 데에 성공했을 때. _randomGiphy를 응답값의 data로 업데이트 한다. 데이터를 10개 받아오는 것이 목적이므로 giphyCount가 10이 될 때까지 getRandomGiphy()를 호출하도록 했다.

.doOnError{}: 데이터를 받아오는 데에 실패했을 때. error log를 찍도록 했다.

.subscribe(): 해당 observable을 구독한다는 의미

 

이렇게 첫번째 기능이었던 랜덤으로 10개의 gif를 받아와서 recyclerView에 띄우는 작업을 완료하였다 !

다음 단계는 여러가지 시나리오를 만들어서 각각의 경우에는 어떤 rxJava 함수가 좋을지 고민해보고 사용해보도록 하겠다. 그럼 다음 포스팅에서 만나요 🙃