Android KTX   Android Jetpack의 일부

Android KTX는 Android Jetpack과 기타 Android 라이브러리와 함께 포함된 Kotlin 확장 프로그램 세트입니다. KTX 확장 프로그램은 간결하고 직관적인 Kotlin을 Jetpack, Android 플랫폼, 기타 API에 제공합니다. 이를 위해 다음을 비롯한 여러 Kotlin 언어 기능을 활용합니다.

  • 확장 함수
  • 확장 속성
  • 람다
  • 이름이 지정된 매개변수
  • 매개변수 기본값
  • 코루틴

예를 들어 SharedPreferences로 작업할 때는 먼저 편집기를 생성해야 환경설정 데이터를 수정할 수 있습니다. 또한 다음 예와 같이 수정이 끝나면 이러한 변경사항을 적용하거나 커밋해야 합니다.

sharedPreferences
        .edit()  // create an Editor
        .putBoolean("key", value)
        .apply() // write to disk asynchronously

Kotlin 람다는 이 사용 사례에 가장 적합합니다. 편집기가 만들어진 후 실행할 코드 블록을 전달하고 코드를 실행한 다음 SharedPreferences API가 변경사항을 원자적으로 적용하도록 하여 더 간결한 방법을 사용할 수 있습니다.

다음은 Android KTX 핵심 함수 중 하나인 SharedPreferences.edit의 예입니다. 이 함수는 SharedPreferences에 수정 함수를 추가합니다. 이 함수는 변경사항을 커밋할지 또는 적용할지 표시하는 첫 번째 인수로 선택적 boolean 플래그를 사용합니다. SharedPreferences 편집기에서 람다 형식으로 실행할 작업도 수신합니다.

// SharedPreferences.edit extension function signature from Android KTX - Core
// inline fun SharedPreferences.edit(
//         commit: Boolean = false,
//         action: SharedPreferences.Editor.() -> Unit)

// Commit a new value asynchronously
sharedPreferences.edit { putBoolean("key", value) }

// Commit a new value synchronously
sharedPreferences.edit(commit = true) { putBoolean("key", value) }

호출자는 변경사항을 커밋할지 또는 적용할지 선택할 수 있습니다. action 람다는 그 자체가 서명으로 표시된 대로 Unit을 반환하는 SharedPreferences.Editor의 익명 확장 함수입니다. 이러한 이유로 블록 내부의 SharedPreferences.Editor에서 직접 작업을 실행할 수 있습니다.

마지막으로 SharedPreferences.edit() 서명에는 inline 키워드가 포함되어 있습니다. 이 키워드는 Kotlin 컴파일러에 함수가 사용될 때마다 함수의 컴파일된 바이트 코드를 복사 및 붙여넣기(또는 인라인) 해야 한다고 알립니다. 이렇게 하면 함수가 호출될 때마다 모든 action의 새로운 클래스를 인스턴스화하는 오버헤드를 방지합니다.

람다를 사용하여 코드를 전달하고 재정의될 수 있는 적절한 기본값을 적용하며 inline 확장 함수를 사용하여 기존 API에 이러한 동작을 추가하는 이 패턴은 Android KTX 라이브러리에서 제공하는 일반적인 개선사항입니다.

프로젝트에 Android KTX 사용

Android KTX 사용을 시작하려면 프로젝트의 build.gradle 파일에 다음 종속 항목을 추가합니다.

Groovy

repositories {
    google()
}

Kotlin

repositories {
    google()
}

AndroidX 모듈

Android KTX는 모듈로 구성되며 각 모듈에는 패키지가 하나 이상 포함됩니다.

앱의 build.gradle 파일에 각 모듈 아티팩트의 종속 항목을 포함해야 합니다. 아티팩트에 버전 번호를 추가해야 합니다. 이 주제의 각 아티팩트 관련 섹션에서 최신 버전 번호를 찾을 수 있습니다.

Android KTX에는 일반 프레임워크 API 및 여러 도메인별 확장 프로그램에 Kotlin 확장 프로그램을 제공하는 단일 핵심 모듈이 포함되어 있습니다.

핵심 모듈을 제외한 모든 KTX 모듈 아티팩트는 build.gradle 파일의 기본 Java 종속 항목을 대체합니다. 예를 들어 androidx.fragment:fragment 종속 항목을 androidx.fragment:fragment-ktx로 대체할 수 있습니다. 이 구문은 버전 관리를 개선하는 데 도움이 되며 종속 항목 선언 요구사항을 추가하지 않습니다.

Core KTX

Core KTX 모듈은 Android 프레임워크의 일부인 일반 라이브러리에 확장 프로그램을 제공합니다. 이러한 라이브러리에는 build.gradle에 추가해야 하는 Java 기반 종속 항목이 없습니다.

이 모듈을 포함하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.core:core-ktx:1.12.0"
}

Kotlin

dependencies {
    implementation("androidx.core:core-ktx:1.12.0")
}

다음은 Core KTX 모듈에 포함된 패키지 목록입니다.

Collection KTX

Collection 확장 프로그램에는 ArrayMap, LongSparseArray, LruCache 등 메모리 효율성이 높은 Android의 컬렉션 라이브러리와 호환되는 유틸리티 함수가 포함되어 있습니다.

이 모듈을 사용하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.collection:collection-ktx:1.4.0"
}

Kotlin

dependencies {
    implementation("androidx.collection:collection-ktx:1.4.0")
}

Collection 확장 프로그램은 다음 예와 같이 Kotlin의 연산자 오버로드를 활용하여 컬렉션 연결과 같은 작업을 단순화합니다.

// Combine 2 ArraySets into 1.
val combinedArraySet = arraySetOf(1, 2, 3) + arraySetOf(4, 5, 6)

// Combine with numbers to create a new sets.
val newArraySet = combinedArraySet + 7 + 8

Fragment KTX

Fragment KTX 모듈은 여러 확장 프로그램을 제공하여 프래그먼트 API를 단순화합니다.

이 모듈을 포함하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.fragment:fragment-ktx:1.6.2"
}

Kotlin

dependencies {
    implementation("androidx.fragment:fragment-ktx:1.6.2")
}

Fragment KTX 모듈을 사용하면 다음과 같이 람다로 프래그먼트 트랜잭션을 단순화할 수 있습니다.

fragmentManager().commit {
   addToBackStack("...")
   setCustomAnimations(
           R.anim.enter_anim,
           R.anim.exit_anim)
   add(fragment, "...")
}

또한 다음과 같이 viewModelsactivityViewModels 속성 위임을 사용하여 한 줄로 ViewModel에 결합할 수도 있습니다.

// Get a reference to the ViewModel scoped to this Fragment
val viewModel by viewModels<MyViewModel>()

// Get a reference to the ViewModel scoped to its Activity
val viewModel by activityViewModels<MyViewModel>()

Lifecycle KTX

Lifecycle KTX는 각 Lifecycle 객체의 LifecycleScope를 정의합니다. 이 범위에서 실행된 코루틴은 Lifecycle이 끝나면 제거됩니다. lifecycle.coroutineScope 또는 lifecycleOwner.lifecycleScope 속성을 사용하여 LifecycleCoroutineScope에 액세스할 수 있습니다.

이 모듈을 포함하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.7.0"
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
}

아래 예는 lifecycleOwner.lifecycleScope를 사용하여 미리 계산된 텍스트를 비동기적으로 만드는 방법을 보여줍니다.

class MyFragment: Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewLifecycleOwner.lifecycleScope.launch {
            val params = TextViewCompat.getTextMetricsParams(textView)
            val precomputedText = withContext(Dispatchers.Default) {
                PrecomputedTextCompat.create(longTextContent, params)
            }
            TextViewCompat.setPrecomputedText(textView, precomputedText)
        }
    }
}

LiveData KTX

LiveData를 사용할 때 값을 비동기적으로 계산해야 할 수 있습니다. 예를 들어 사용자의 환경설정을 검색하여 UI에 제공하려고 할 수 있습니다. 이런 상황에서 LiveData KTX는 liveData 빌더 함수를 제공함으로써 suspend 함수를 호출하여 그 결과를 LiveData 객체로 제공할 수 있습니다.

이 모듈을 포함하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.7.0"
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.7.0")
}

다음 예에서 loadUser()는 다른 곳에서 선언된 정지 함수입니다. liveData 빌더 함수를 사용하여 loadUser()를 비동기적으로 호출한 후 emit()를 사용하여 결과를 내보낼 수 있습니다.

val user: LiveData<User> = liveData {
    val data = database.loadUser() // loadUser is a suspend function.
    emit(data)
}

LiveData와 함께 코루틴을 사용하는 방법에 관한 자세한 내용은 아키텍처 구성요소와 함께 Kotlin 코루틴 사용을 참조하세요.

Navigation 라이브러리의 각 구성요소에는 API를 조정하여 더 간결하고 Kotlin 직관적이 되도록 하는 자체 KTX 버전이 있습니다.

이러한 모듈을 포함하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.navigation:navigation-runtime-ktx:2.7.7"
    implementation "androidx.navigation:navigation-fragment-ktx:2.7.7"
    implementation "androidx.navigation:navigation-ui-ktx:2.7.7"
}

Kotlin

dependencies {
    implementation("androidx.navigation:navigation-runtime-ktx:2.7.7")
    implementation("androidx.navigation:navigation-fragment-ktx:2.7.7")
    implementation("androidx.navigation:navigation-ui-ktx:2.7.7")
}

다음 예와 같이 확장 함수 및 속성 위임을 사용하여 대상 인수에 액세스하고 대상을 탐색합니다.

class MyDestination : Fragment() {

    // Type-safe arguments are accessed from the bundle.
    val args by navArgs<MyDestinationArgs>()

    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        view.findViewById<Button>(R.id.next)
            .setOnClickListener {
                // Fragment extension added to retrieve a NavController from
                // any destination.
                findNavController().navigate(R.id.action_to_next_destination)
            }
     }
     ...

}

Palette KTX

Palette KTX 모듈은 색상 팔레트 작업에 직관적인 Kotlin 지원을 제공합니다.

이 모듈을 사용하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.palette:palette-ktx:1.0.0"
}

Kotlin

dependencies {
    implementation("androidx.palette:palette-ktx:1.0.0")
}

예를 들어 Palette 인스턴스로 작업할 때 get 연산자([ ])를 사용하여 주어진 targetselected 견본을 검색할 수 있습니다.

val palette = Palette.from(bitmap).generate()
val swatch = palette[target]

Reactive Streams KTX

Reactive Streams KTX 모듈을 사용하면 ReactiveStreams 게시자에서 식별 가능한 LiveData 스트림을 생성할 수 있습니다.

이 모듈을 포함하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:2.7.0"
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:2.7.0")
}

예를 들어 작은 사용자 목록이 있는 데이터베이스를 가정해보겠습니다. 앱에서 데이터베이스를 메모리로 로드한 다음 UI에 사용자 데이터를 표시합니다. 이를 위해 RxJava를 사용할 수 있습니다. Room Jetpack 구성요소는 사용자 목록을 Flowable로 검색할 수 있습니다. 이 시나리오에서는 프래그먼트나 활동의 수명 전체에 걸쳐 Rx 게시자 구독도 관리해야 합니다.

그러나 다음 예와 같이 LiveDataReactiveStreams를 사용하면 RxJava 및 다양한 연산자 세트와 작업 일정 예약 기능의 이점은 물론 LiveData의 단순성이라는 이점도 누릴 수 있습니다.

val fun getUsersLiveData() : LiveData<List<User>> {
    val users: Flowable<List<User>> = dao.findUsers()
    return LiveDataReactiveStreams.fromPublisher(users)
}

Room KTX

Room 확장 프로그램은 데이터베이스 트랜잭션을 위한 코루틴 지원을 추가합니다.

이 모듈을 사용하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.room:room-ktx:2.6.1"
}

Kotlin

dependencies {
    implementation("androidx.room:room-ktx:2.6.1")
}

다음은 Room에서 현재 코루틴을 사용하는 몇 가지 예입니다. 첫 번째 예에서는 suspend 함수를 사용하여 User 객체 목록을 반환하는 반면 두 번째 예에서는 Kotlin의 Flow를 활용하여 User 목록을 비동기적으로 반환합니다. Flow 사용 시 쿼리 중인 테이블의 변경사항 알림을 받습니다.

@Query("SELECT * FROM Users")
suspend fun getUsers(): List<User>

@Query("SELECT * FROM Users")
fun getUsers(): Flow<List<User>>

SQLite KTX

SQLite 확장 프로그램은 트랜잭션에서 SQL 관련 코드를 래핑하여 여러 상용구 코드를 제거합니다.

이 모듈을 사용하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.sqlite:sqlite-ktx:2.4.0"
}

Kotlin

dependencies {
    implementation("androidx.sqlite:sqlite-ktx:2.4.0")
}

다음은 transaction 확장을 사용하여 데이터베이스 트랜잭션을 실행하는 예입니다.

db.transaction {
    // insert data
}

ViewModel KTX

ViewModel KTX 라이브러리는 viewModelScope() 함수를 제공합니다. 이 함수로 ViewModel에서 코루틴을 실행하기가 더 쉬워집니다. CoroutineScopeDispatchers.Main에 바인딩되며 ViewModel이 삭제되면 자동으로 취소됩니다. 각 ViewModel에 새로운 범위를 만드는 대신 viewModelScope()을 사용할 수 있습니다.

이 모듈을 포함하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0"
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0")
}

예를 들어 다음 viewModelScope() 함수는 백그라운드 스레드에서 네트워크를 요청하는 코루틴을 실행합니다. 라이브러리는 모든 설정 및 상응하는 범위 삭제를 처리합니다.

class MainViewModel : ViewModel() {
    // Make a network request without blocking the UI thread
    private fun makeNetworkRequest() {
        // launch a coroutine in viewModelScope
        viewModelScope.launch  {
            remoteApi.slowFetch()
            ...
        }
    }

    // No need to override onCleared()
}

WorkManager KTX

WorkManager KTX는 코루틴을 위한 최고 수준의 지원을 제공합니다.

이 모듈을 포함하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "androidx.work:work-runtime-ktx:2.9.0"
}

Kotlin

dependencies {
    implementation("androidx.work:work-runtime-ktx:2.9.0")
}

Worker를 확장하는 대신 API가 약간 다른 CoroutineWorker를 확장할 수 있습니다. 예를 들어 간단한 CoroutineWorker를 빌드하여 일부 네트워크 작업을 실행하려면 다음과 같이 하면 됩니다.

class CoroutineDownloadWorker(context: Context, params: WorkerParameters)
        : CoroutineWorker(context, params) {

    override suspend fun doWork(): Result = coroutineScope {
        val jobs = (0 until 100).map {
            async {
                downloadSynchronously("https://www.google.com")
            }
        }

        // awaitAll will throw an exception if a download fails, which
        // CoroutineWorker will treat as a failure
        jobs.awaitAll()
        Result.success()
    }
}

CoroutineWorker 사용에 관한 자세한 내용은 CoroutineWorker의 스레딩을 참조하세요.

또한 WorkManager KTX는 OperationsListenableFutures에 확장 함수를 추가하여 현재 코루틴을 정지합니다.

다음은 enqueue()에 의해 반환된 Operation을 정지하는 예입니다.

// Inside of a coroutine...

// Run async operation and suspend until completed.
WorkManager.getInstance()
        .beginWith(longWorkRequest)
        .enqueue().await()

// Resume after work completes...

기타 KTX 모듈

또한 AndroidX 외부에 있는 추가 KTX 모듈을 포함할 수도 있습니다.

Firebase KTX

일부 Android용 Firebase SDK에는 앱에서 Firebase를 사용할 때 직관적인 Kotlin 코드를 작성할 수 있게 하는 Kotlin 확장 라이브러리가 있습니다. 자세한 내용은 다음 주제를 참조하세요.

Google Maps Platform KTX

Google Maps Platform Android SDK에 사용할 수 있는 KTX 확장 프로그램이 있으며 이를 사용하면 확장 함수, 명명된 매개변수와 기본 인수, 구조 파괴 선언, 코루틴과 같은 여러 Kotlin 언어 기능을 활용할 수 있습니다. 자세한 내용은 다음 항목을 참조하세요.

Play Core KTX

Play Core KTX는 Play Core 라이브러리의 SplitInstallManagerAppUpdateManager에 확장 함수를 추가하여 원샷 요청의 Kotlin 코루틴 지원 및 상태 업데이트 모니터링의 Flow 지원을 추가합니다.

이 모듈을 포함하려면 앱의 build.gradle 파일에 다음을 추가합니다.

Groovy

dependencies {
    implementation "com.google.android.play:core-ktx:1.8.1"
}

Kotlin

dependencies {
    implementation("com.google.android.play:core-ktx:1.8.1")
}

다음은 상태 모니터링 Flow의 예입니다.

// Inside of a coroutine...

// Request in-app update status updates.
manager.requestUpdateFlow().collect { updateResult ->
    when (updateResult) {
        is AppUpdateResult.Available -> TODO()
        is AppUpdateResult.InProgress -> TODO()
        is AppUpdateResult.Downloaded -> TODO()
        AppUpdateResult.NotAvailable -> TODO()
    }
}

추가 정보

Android KTX에 관한 자세한 내용은 DevBytes 동영상을 참조하세요.

문제를 신고하거나 기능을 제안하려면 Android KTX Issue Tracker를 사용하세요.