RxKotlin & RxKotlinFx란?

RxKotlin에 대해선 이전에 쓴 글 (https://velog.io/@riemannulus/ReactiveX%EC%99%80%EC%9D%98-%EC%B2%AB-%EB%A7%8C%EB%82%A8-tyk156kys5) 에 자세히 설명해 놓았다.

RxKotlinFx는?

JavaFx를 Kotlin 버전으로 바꾼 KotlinFx(TornadoFx)를 좀 더 Rx하게 사용할 수 있게 만든 프레임워크이다.

장점?

UI/UX의 골칫거리인 비동기 작업을 쉽게 처리할 수 있고, Java의 골칫거리인 비동기 함수형에서의 예외 처리를 한 번에 해결 가능하다.

단점?

프로그램 구조에 대해 접근하는 방식을 좀 바꿔야 한다. 이벤트에 대한 반응형이기 때문에 이벤트 구독을 해지하지 않으면 계속 이벤트를 감시하면서 메모리 리크가 일어날 가능성이 있다.

시작하기

실습환경

MacOS 10.14.6 Mojave
IntelliJ IDEA 2019.2.1 (Ultimate Edition)
Oracle Java8 SE (Fx를 사용하므로 Oracle EE가 꼭 필요하다)

환경설정

프로젝트 생성

먼저 프로젝트를 생성해 준다. Gradle을 선택해 주고 Java, Kotlin/JVM 을 체크, 그리고 Project SDK는 1.8(Oracle)로 설정해 준다. Kotlin DSL은 선택사항이나 잘 모르겠으면 체크하고 넘어갈 것.
IntelliJ gradle new project window, checked java and Kotlin/JVM wit java1.8 version. check kotlin dsl build script

다음은 프로젝트 정보를 적으면 된다. 원하는 대로 적고 다음을 눌러준다.
group id: me.hanaoto, artifactId: rxjavafx-playground, version 1.0-SNAPSHOT

저장 위치를 지정하고 넘어가자.
project name: rxjavafx-playground, Project location: ~/Workspace/rxjavafx-playground

프로젝트가 생성되었으면 build.gradle.kts 를 열고 디펜던시에 다음 라이브러리들을 추가해 준다.

    implementation("com.github.thomasnield:rxkotlinfx:2.2.2")
    implementation("no.tornado:tornadofx:1.7.19")
    implementation("io.reactivex.rxjava2:rxkotlin:2.4.0")

build.gradle.kts with some dependencies

메인 클래스 생성

이제 Hello World를 찍어보자. 간단하게 짤 수 있다.
kotlin 파일을 하나 생성하고 다음 코드를 짜 넣자.

import tornadofx.*

class MainApplication: App(MainView::class)

class MainView: View() {
  override val root = vbox {
       label("hello world!") 
  }
}

some code block

이제 실행을 시킬 차례이다. Add new configuration->Application 을 선택해 주자.

mouse point hover on application section

다음과 같이 설정해 주면 된다. Main class에는 앞에서 생성했던 클래스를, Use classpath of module에는 우리 프로젝트의 main을 지정하면 된다. JRE는 1.8 SE임을 확인하고 OK를 누른다.

Some setting of application

이제 실행시키면 :Tada:

windows, an single line 'hello world!'

More Rx

여기까지는 그냥 TornadoRx 아닌가요? 라고 할 만 하다. 이제 좀 더 "RX" 스러운 걸 해 보자. 클릭을 할 때마다 카운트가 올라가고, 10이 되면 멈추는 애플리케이션을 만들어보고자 한다.

기존의 방법으로는 UI 쓰레드에 카운트를 세는 변수를 하나 만들고, 클릭할 때 마다 이 변수로부터 값을 가져와서 하나 증가 후 UI 쓰레드를 갱신해야 할 것이다. 하지만 Rx를 쓰면 조금 다르다. 클릭을 하면 스트림에 데이터가 들어오고, 데이터에 대해 반응한다. 코드는 다음과 같다.:

import com.github.thomasnield.rxkotlinfx.actionEvents
import io.reactivex.rxkotlin.subscribeBy
import tornadofx.*

class MainApplication: App(MainView::class)

class MainView: View() {

    override val root = vbox {

        val countLabel = label("0")
        val doneLabel = label("")

        button("Press Me")
            .actionEvents()
            .map { 1 }
            .scan(0) {x,y -> x + y }
            .take(5)
            .subscribeBy(
                onNext =  { countLabel.text = it.toString() },
                onError = { it.printStackTrace() },
                onComplete = { doneLabel.text = "Done!" }
            )
    }
}

click event code

처음부터 보자. 일단 button이 눌리면 일어나는 액션에 대한 이벤트를 정의한다. 1이라는 값을 발생시키고, 값이 발생할 때마다 이전 값에 발생한 값을 더한 후, 5 밑일 경우에는 구독한 이벤트를 실행한다. 실행시켜보면 잘 동작함을 알 수 있다.

step by 1 when click 'press me!', end if number is 4

마치며

차회예고

다음은 본격적인 이벤트 스트림 제어와 좀 더 많은 예제를 들고 오겠다.