Kotlin에서 Retrofit 및 Rx를 사용하여 API 클라이언트를 신속하게 구현

Retrofit은 API 클라이언트를 만드는 데 사용되는 라이브러리입니다.
인터페이스만 정의하면 제작할 수 있어 매우 가볍다.
Retrofit는 RxJava를 사용하여 비동기 처리를 잘 쓸 수 있으며 HTTP 통신에서는 OkHttp를 사용하고 JSON의 퍼스에서 moshi를 사용하여 API 클라이언트를 실현할 수 있다.
실제로 어떻게 사용하는지 해보고 싶어요.

환경


Mac OSX
Android Studio 2.0
Kotlin 1.0.0-beta-2423
Android Studio에 Kotlin 플러그인을 넣으십시오.

항목 만들기


우선, BlankActivity가 있는 프로젝트를 적절하게 만듭니다.
생성된 Java 소스 코드를 Kotlin으로 변환합니다.
위의 메뉴에서 Code->Convert Java File to Kotlin File을 사용하여 변환할 수 있습니다.app/build.gradle에 다음 내용 추가
build.gradle
+apply plugin: 'kotlin-android'

dependencies {
    ...
+    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+    compile 'io.reactivex:rxkotlin:0.24.100'
+    compile 'io.reactivex:rxandroid:1.0.1'
+    compile 'io.reactivex:rxjava:1.0.15'
+    compile 'com.squareup.okhttp:okhttp:2.0.0'
+    compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0'
+    compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
+    compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
+    compile 'com.squareup.retrofit:converter-moshi:2.0.0-beta2'

}

+buildscript {
+    ext.kotlin_version = '1.0.0-beta-2423'
+    repositories {
+        mavenCentral()
+    }
+    dependencies {
+        classpath "org.jetbrains.kotlin:kotlin-gradle-+plugin:$kotlin_version"
+        classpath "org.jetbrains.kotlin:kotlin-android-+extensions:$kotlin_version"
+    }
+}
일단 빌딩이 지나간 곳을 확인해 볼게요.

실시


Retrofit 인터페이스를 만듭니다.
이번 목적은 Rx를 사용하기 때문에 인터페이스도 Rx를 사용합니다.
interface SplatoonService {
    @GET("/schedule.json")
    fun schedule(): Observable<ScheduleResponse>
}
점은 rx로 되돌아오는 값입니다.Observable입니다.
Schedule Response 오징어처럼.
data class ScheduleResponse(
        var updateTime: Long,
        var schedule: List<Schedule>
) : Serializable

data class Schedule(
        var startTime: Long,
        var endTime: Long,
        var regular: Match,
        var ranked: Match
): Serializable

data class Match(
        var maps: List<Map>,
        var rulesJP: String = "ナワバリバトル",
        var rulesEN: String = "Turf War"
): Serializable

data class Map(
        var nameJP: String,
        var nameEN: String
): Serializable
API 클라이언트 인스턴스를 생성합니다.
fun client(): SplatoonService {
        val moshi = Moshi.Builder()
                .build()

        val okClient = OkHttpClient()

        val builder = Retrofit.Builder()
                .client(okClient)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(MoshiConverterFactory.create(moshi))
                .baseUrl("https://splatoon.ink")
                .build()

        return builder.create(SplatoonService::class.java)
}

사용 방법


사용 방법은 다음과 같다.
client().schedule().
       subscribeOn(Schedulers.newThread()).
       observeOn(AndroidSchedulers.mainThread()).
       subscribe(object : Subscriber<ScheduleResponse>(){
           override fun onNext(r: ScheduleResponse?) {
               ...
           }

           override fun onError(e: Throwable?) {
               ...
           }
       })

이 코드가 UIThread에서 실행되는 경우.subscribeOn(Schedulers.newThread()) 다른 스레드에서 실행
문서 레지스트리에 항목을 추가합니다.

지루한 부분을 좀 개선하다


그저 그렇다면 얻기 어려운 kotlin,subscribe의 장소는 지루해졌다.
나는 람다식으로 더 좋은 느낌을 쓸 수 있도록 확장 함수를 사용해 보았다.
public fun <T> Observable<T>.onError(block : (Throwable) -> Unit): KSubscription<T> {
    return KSubscription(this).onError(block)
}

public fun <T> Observable<T>.onCompleted(block : () -> Unit): KSubscription<T> {
    return KSubscription(this).onCompleted(block)
}

public fun <T> Observable<T>.onNext(block : (T) -> Unit): KSubscription<T> {
    return KSubscription(this).onNext(block)
}

public fun Subscription.onError(block: (Throwable) -> Unit): Subscription {
    return this
}

public class KSubscription<T>(val observable: Observable<T>) {

    private var error: (Throwable) -> Unit = { throw it }
    private var completed: () -> Unit = {}
    private var next: (T) -> Unit = {}

    fun onError(block: (Throwable) -> Unit): KSubscription<T> {
        error = block
        return this
    }

    fun onCompleted(block: () -> Unit): KSubscription<T> {
        completed = block
        return this
    }

    fun onNext(block: (T) -> Unit): KSubscription<T> {
        next = block
        return this
    }

    fun subscribe(): Subscription = observable.subscribe(object : Subscriber<T>(){
            override fun onError(e: Throwable?) {
                if ( e == null ) {
                    return
                }

                error.invoke(e)
            }

            override fun onCompleted() {
                completed.invoke()
            }

            override fun onNext(t: T) {
                next.invoke(t)
            }
        })
}
너는 방금 전의 코드를 이렇게 쓸 수 있다.
client().schedule().
       subscribeOn(Schedulers.newThread()).
       observeOn(AndroidSchedulers.mainThread()).
       onNext {
           ...
       }.
       onError {
           ...
       }.
       subscribe()

총결산



따라서 아주 적은 코드로 API 클라이언트를 실현할 수 있다.
글쎄요. 잘 쓰면 네트워크가 연결되었는지 Token에 접근했는지 확인하고 싶어요. 모두 onError에 넣으세요.
Java로 이걸 하려면 먼저 Observable를 매개 변수로 전달해야 합니다
만약 당신이 방법 체인을 세우고 싶다면, 클래스를 계승해서 그것을 포장해 보아야 한다
Kotlin이라면 캐주얼하게 추가할 수 있는 방법이 편리합니다.

좋은 웹페이지 즐겨찾기