반응형

Retrofit

설명

  • API 통신을 도와주는 라이브러리
  • 기존의 HttpConnection을 활용한 방법보다 비동기 처리가 쉽고, 속도도 다른 라이브러리보다 빠른 장점을 갖는다.
  • 내부적으로 OkHttp를 사용한다.
  • 상세 사용법은 아래 참고

기본 예제

manifests/AndroidManifest.xml
  • INTERNET 퍼미션 추가 필요
<uses-permission android:name="android.permission.INTERNET" />
build.gradle
dependencies {
    ...
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
}
Comment
data class Comment(
    var postId: Int,
    var id: Int,
    var name: String,
    var email: String,
    var body: String
)
DemoApi
interface DemoApi {
    @GET("todos/{id}/comments")
    fun getComments(@Path("id") id: Int): Call<List<Comment>>
}
호출
val retrofit = Retrofit.Builder()
    .baseUrl("https://jsonplaceholder.typicode.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build()

val demoApi = retrofit.create(DemoApi::class.java)

demoApi.getComments(1).enqueue(object: Callback<List<Comment>>{
    override fun onResponse(call: Call<List<Comment>>, response: Response<List<Comment>>) {
        Toast.makeText(this@MainActivity, response.body().toString(), Toast.LENGTH_SHORT).show()
    }

    override fun onFailure(call: Call<List<Comment>>, t: Throwable) {
        TODO("Not yet implemented")
    }
})

RxJava를 활용한 예제

  • 기본적인 코드는 위 내용과 동일
build.gradle
dependencies {
    ...
    implementation "com.squareup.retrofit2:adapter-rxjava2:2.3.0"
    implementation "io.reactivex.rxjava2:rxandroid:2.0.1"
}
DemoApi
interface DemoApi {
    @GET("todos/{id}/comments")
    fun getComments(@Path("id") id: Int): Observable<List<Comment>> // Call에서 Observable로 변경
}
사용
fun callApi() {
    val retrofit = Retrofit.Builder()
        .baseUrl("https://jsonplaceholder.typicode.com/")
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val demoApi = retrofit.create(DemoApi::class.java)

    val disposable = demoApi.getComments(1)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            { comments -> Toast.makeText(this, comments.toString(), Toast.LENGTH_SHORT).show() },
            { error -> Toast.makeText(this, error.toString(), Toast.LENGTH_SHORT).show() }
        )

    // disposable.dispose() // 호출시 HTTP 통신 도중 종료
}

OkHttp 사용 예제

fun callApi() {
    val client = OkHttpClient.Builder()
        .connectTimeout(15, TimeUnit.SECONDS)
        .readTimeout(15, TimeUnit.SECONDS)
        .build()

    val retrofit = Retrofit.Builder()
        .client(client) // okHttp 클라이언트 추가
        .baseUrl("https://jsonplaceholder.typicode.com/")
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val demoApi = retrofit.create(DemoApi::class.java)

    val disposable = demoApi.getComments(1)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            { comments -> Toast.makeText(this, comments.toString(), Toast.LENGTH_SHORT).show() },
            { error -> Toast.makeText(this, error.toString(), Toast.LENGTH_SHORT).show() }
        )

    // disposable.dispose() // 호출시 HTTP 통신 도중 종료
}

Interceptor 사용 예제

fun callApi() {
    val client = OkHttpClient.Builder()
        .connectTimeout(15, TimeUnit.SECONDS)
        .readTimeout(15, TimeUnit.SECONDS)
        .addInterceptor(CustomInterceptor()) // Interceptor 추가
        .build()

    val retrofit = Retrofit.Builder()
        .client(client)
        .baseUrl("https://jsonplaceholder.typicode.com/")
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val demoApi = retrofit.create(DemoApi::class.java)

    val disposable = demoApi.getComments(1)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            { comments -> Toast.makeText(this, comments.toString(), Toast.LENGTH_SHORT).show() },
            { error -> Toast.makeText(this, error.toString(), Toast.LENGTH_SHORT).show() }
        )

    // disposable.dispose() // 호출시 HTTP 통신 도중 종료
}

inner class CustomInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        Log.d("TEST", "${chain.request().method()} - ${chain.request().url()}")

        val request = chain.request().newBuilder().addHeader("token", "test-token").build()
        val response = chain.proceed(request)

        return response
    }
}

Converter 사용 예제

fun callApi() {
    val client = OkHttpClient.Builder()
        .connectTimeout(15, TimeUnit.SECONDS)
        .readTimeout(15, TimeUnit.SECONDS)
        .build()

    val retrofit = Retrofit.Builder()
        .client(client)
        .baseUrl("https://jsonplaceholder.typicode.com/")
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .addConverterFactory(CustomConverterFactory()) // Converter 설정
        .build()

    val demoApi = retrofit.create(DemoApi::class.java)

    val disposable = demoApi.getComments(1)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(
            { comments -> Toast.makeText(this, comments.toString(), Toast.LENGTH_SHORT).show() },
            { error -> Toast.makeText(this, error.toString(), Toast.LENGTH_SHORT).show() }
        )

    // disposable.dispose() // 호출시 HTTP 통신 도중 종료
}

inner class CustomConverterFactory : Converter.Factory() {
    override fun responseBodyConverter(type: Type, annotations: Array<Annotation>, retrofit: Retrofit): Converter<ResponseBody, *>? {
        val gson = Gson()
        val adapter = gson.getAdapter(TypeToken.get(type))

        return object : Converter<ResponseBody, Any> {
            override fun convert(value: ResponseBody): Any? {
                try {
                    val jsonReader = gson.newJsonReader(value.charStream())
                    val result = adapter.read(jsonReader)

                    return result
                } finally {
                    value.close()
                }
            }
        }
    }
}

참고

반응형

'Development > Android' 카테고리의 다른 글

[Android] SharedPreferences  (0) 2021.02.09
[Android] Build APK  (0) 2021.02.09
[Android] Lottie  (0) 2021.02.09
[Android] Http Network  (0) 2021.02.09
[Android] File IO  (0) 2021.02.09

+ Recent posts