Android Jetpack – Lifecycle in JDK8

도입

Android Jetpack 중에서 Lifecycle-Aware Components라는 컴포넌트가 있다. 이 컴포넌트는 Activity나 Fragment 같은 안드로이드의 자체 Lifecycle를 가지는 클래스의 Lifecycle 이벤트를 비-Activity 클래스, 즉 ViewModel 이나 Manager 등에 전달할 수 있는 역할을 가진다.

사용 방법은 대체로 간단한데, 받는 쪽에서는 LifecycleObserver 를 구현하고 @OnLifecycleEvent(ON_RESUME) 의 어노테이션을 부착하면 되고, Activity 에서는 lifecycle.addObserver(viewModel) 를 사용하면 ViewModel 등에서 ON_RESUME, ON_PAUSE, ON_DESTROY 등의 이벤트를 받을 수 있다.

@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
open fun onDestroy() {
    compositeDisposable.clear()
}

다만 이 Lifecycle-aware Components를 사용할 때에 JDK 8를 이상으로 하고 JDK 8의 언어 지원 기능을 사용하는 프로젝트라면 사용 방법이 다른데, 이에 대해 알아보려 한다.

JDK 8 언어 지원 기능 사용시

Lifecycle 의 클래스 주석에는 아래와 같은 내용이 있다.

 * If you use <b>Java 8 Language</b>, then observe events with {@link DefaultLifecycleObserver}.
 * To include it you should add {@code "androidx.lifecycle:common-java8:<version>"} to your
 * build.gradle file.
 * <pre>
 * class TestObserver implements DefaultLifecycleObserver {
 *     {@literal @}Override
 *     public void onCreate(LifecycleOwner owner) {
 *         // your code
 *     }
 * }
 * </pre>

Java 8에서는 Default Interface라고 하는, 인터페이스에 기본적인 코드 형태를 가질 수 있게 하는 기능이 신규로 나오면서 더 이상 Annotation Processor와 Reflection을 기반으로 하는 @OnLifecycleEvent가 필요가 없어진 것이다. (또한 Java 8이 안드로이드의 메인 스트림이 되면 @OnLifecycleEvent를 Deprecated 할 예정이라고도 한다.)

기존에 사용하던 OnLifecycleEvent를 DefaultLifecycleObserver로 변경하려면 Gradle에 아래 의존성을 추가한다.

 implementation group: 'android.arch.lifecycle', name: 'common-java8', version: '1.1.1'

문서 작성일(2018-12-04) 기준 최신 버전은 1.1.1로,  Maven Repository 사이트에서 최신 버전을 참고하면 된다.

의존성을 추가한 뒤에는 LifecycleObserver를 구현하는 대신 DefaultLifecycleObserver 를 구현받고 onResume, onPause 등을 오버라이드 하면 된다.

override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        compositeDisposable.clear()
}

오류:  Super call to java default methods are prohibited in jvm target 1.6

이는 Kotlin compiler가 JVM 타겟을 1.8이 아닌 1.6으로 잡고 있어서 발생하는 상황이다. 해결을 위해서는 아래 옵션을 build.gradle 의 android 섹션 밑에 두면 된다.

kotlinOptions {
        jvmTarget = '1.8'
}