Android KTX חלק מ-Android Jetpack.
Android KTX היא קבוצה של תוספים ל-Kotlin שכלולים ב-Android Jetpack ובספריות אחרות של Android. תוספים של KTX מספקים קוד Kotlin תמציתי וסגנוני ל-Jetpack, לפלטפורמת Android ולממשקי API אחרים. כדי לעשות זאת, התוספים האלה משתמשים בכמה תכונות של שפת Kotlin, כולל:
- פונקציות של תוספים
- מאפייני התוספים
- פונקציות Lambda
- פרמטרים עם שם
- ערכי ברירת המחדל של הפרמטרים
- שגרות המשך (coroutines)
לדוגמה, כשעובדים עם SharedPreferences
, צריך ליצור עורך כדי שתוכלו לבצע שינויים בנתוני ההעדפות. בסיום העריכה, צריך גם להחיל או לאשר את השינויים האלה, כפי שמתואר בדוגמה הבאה:
sharedPreferences
.edit() // create an Editor
.putBoolean("key", value)
.apply() // write to disk asynchronously
פונקציות הלמה של Kotlin מתאימות בצורה מושלמת לתרחיש לדוגמה הזה. הם מאפשרים לכם להשתמש בגישה תמציתית יותר, על ידי העברת בלוק של קוד לביצוע אחרי יצירת העורך, ביצוע הקוד ולאחר מכן החלת השינויים באופן אטומי על ידי SharedPreferences
API.
הנה דוגמה לאחת מהפונקציות של Android KTX Core, SharedPreferences.edit
, שמוסיפה פונקציית עריכה ל-SharedPreferences
. הפונקציה הזו מקבלת את הדגל האופציונלי boolean
כארגומנט הראשון שלה, שמציין אם צריך לבצע את השינויים או להחיל אותם. הוא מקבל גם פעולה לביצוע בעורך SharedPreferences
בצורת פונקציית lambda.
// 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) }
מבצע הקריאה יכול לבחור אם לשמור או להחיל את השינויים. פונקציית lambda action
היא בעצמה פונקציית תוסף אנונימית ב-SharedPreferences.Editor
שמחזירה את הערך Unit
, כפי שמצוין בחתימתה. לכן, בתוך הבלוק אפשר לבצע את העבודה ישירות ב-SharedPreferences.Editor
.
לבסוף, החתימה SharedPreferences.edit()
מכילה את מילת המפתח inline
.
מילת המפתח הזו מורה למהדר של Kotlin להעתיק ולהדביק (או להטמיע) את הקוד הבינארי המהדר של הפונקציה בכל פעם שמשתמשים בפונקציה.
כך אפשר למנוע את העלויות הנלוות של יצירת מופע חדש של כל action
בכל פעם שמפעילים את הפונקציה הזו.
התבנית הזו של העברת קוד באמצעות פונקציות lambda, החלת ברירת מחדל הגיוניות שאפשר לשנות ולהוסיף את ההתנהגויות האלה לממשקי API קיימים באמצעות פונקציות ההרחבה inline
היא אופיינית לשיפורים שספריית KTX ל-Android מספקת.
שימוש ב-Android KTX בפרויקט
כדי להתחיל להשתמש ב-Android KTX, מוסיפים את התלות הבאה לקובץ build.gradle
של הפרויקט:
Groovy
repositories { google() }
Kotlin
repositories { google() }
מודולים של AndroidX
Android KTX מחולק למודולים, וכל מודול מכיל חבילת קוד אחת או יותר.
צריך לכלול יחסי תלות לכל ארטיפקט של מודול בקובץ build.gradle
של האפליקציה. חשוב לזכור לצרף את מספר הגרסה לארטיפקט.
מספרי הגרסאות העדכניים ביותר מופיעים בקטע המתאים של כל ארטיפקט בנושא הזה.
Android KTX מכיל מודול ליבה יחיד שמספק תוספים של Kotlin לממשקי API נפוצים של מסגרות וכמה תוספים ספציפיים לדומיין.
מלבד מודול הליבה, כל הארטיפקטים של מודול KTX מחליפים את התלות הבסיסית ב-Java בקובץ build.gradle
. לדוגמה, אפשר להחליף את התלות ב-androidx.fragment:fragment
ב-androidx.fragment:fragment-ktx
. התחביר הזה עוזר לנהל טוב יותר את ניהול הגרסאות, ולא מוסיף דרישות נוספות להצהרת התלות.
Core KTX
המודול Core KTX מספק תוספים לספריות נפוצות שנכללות במסגרת Android. לספריות האלה אין יחסי תלות מבוססי-Java שצריך להוסיף ל-build.gradle
.
כדי לכלול את המודול הזה, מוסיפים את הנתונים הבאים לקובץ build.gradle
של האפליקציה:
מגניב
dependencies { implementation "androidx.core:core-ktx:1.13.1" }
Kotlin
dependencies { implementation("androidx.core:core-ktx:1.13.1") }
זו רשימה של החבילות שמכיל מודול Core KTX:
- androidx.core.animation
- androidx.core.content
- androidx.core.content.res
- androidx.core.database
- androidx.core.database.sqlite
- androidx.core.graphics
- androidx.core.graphics.drawable
- androidx.core.location
- androidx.core.net
- androidx.core.os
- androidx.core.text
- androidx.core.transition
- androidx.core.util
- androidx.core.view
- androidx.core.widget
Collection KTX
התוספים של Collection מכילים פונקציות שימושיות לעבודה עם ספריות האוספים של Android, שיעילות בשימוש בזיכרון, כולל ArrayMap
, LongSparseArray
, LruCache
ועוד.
כדי להשתמש במודול הזה, מוסיפים את הקוד הבא לקובץ build.gradle
של האפליקציה:
Groovy
dependencies { implementation "androidx.collection:collection-ktx:1.4.5" }
Kotlin
dependencies { implementation("androidx.collection:collection-ktx:1.4.5") }
התוספים של האוספים מנצלים את עומס היתר של האופרטורים ב-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
המודול KTX של קטעי הקוד מספק מספר תוספים שמפשטים את ממשק ה-API של קטעי הקוד.
כדי לכלול את המודול הזה, מוסיפים את הנתונים הבאים לקובץ build.gradle
של האפליקציה:
מגניב
dependencies { implementation "androidx.fragment:fragment-ktx:1.8.3" }
Kotlin
dependencies { implementation("androidx.fragment:fragment-ktx:1.8.3") }
בעזרת מודול Fragment KTX אפשר לפשט טרנזקציות של קטעים באמצעות פונקציות lambda, לדוגמה:
fragmentManager().commit {
addToBackStack("...")
setCustomAnimations(
R.anim.enter_anim,
R.anim.exit_anim)
add(fragment, "...")
}
אפשר גם לקשר ל-ViewModel
בשורה אחת באמצעות נציגי המאפיינים viewModels
ו-activityViewModels
:
// 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 מוגדר LifecycleScope
לכל אובייקט Lifecycle
. כל רצף משימות מרובות (coroutine) שמופעל בהיקף הזה מבוטל כשה-Lifecycle
נהרס. אפשר לגשת ל-CoroutineScope
של ה-Lifecycle
באמצעות המאפיינים lifecycle.coroutineScope
או lifecycleOwner.lifecycleScope
.
כדי לכלול את המודול הזה, מוסיפים את הנתונים הבאים לקובץ build.gradle
של האפליקציה:
מגניב
dependencies { implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.7" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7") }
הדוגמה הבאה ממחישה איך משתמשים ב-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, יכול להיות שתצטרכו לחשב ערכים באופן אסינכרוני. לדוגמה, יכול להיות שתרצו לאחזר את ההעדפות של משתמש ולהציג אותן בממשק המשתמש. במקרים כאלה, LiveData KTX מספקת פונקציית build liveData
שמפעילה פונקציית suspend
ומציגה את התוצאה כאובייקט LiveData
.
כדי לכלול את המודול הזה, מוסיפים את הנתונים הבאים לקובץ build.gradle
של האפליקציה:
מגניב
dependencies { implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.7" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.7") }
בדוגמה הבאה, loadUser()
היא פונקציית השהיה שהוגדרה במקום אחר.
אפשר להשתמש בפונקציית ה-builder liveData
כדי לבצע קריאה אסינכרונית ל-loadUser()
, ואז להשתמש ב-emit()
כדי להפיק את התוצאה:
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
למידע נוסף על שימוש בשגרות המשך (coroutines) עם LiveData
, קראו את המאמר שימוש בשגרות המשך (coroutines) ב-Kotlin עם רכיבי ארכיטקטורה.
Navigation KTX
לכל רכיב בספריית הניווט יש גרסה משלו של KTX שמתאימה את ה-API כך שיהיה תמציתי יותר ותואמת ל-Kotlin.
כדי לכלול את המודולים האלה, מוסיפים את הנתונים הבאים לקובץ build.gradle
של האפליקציה:
Groovy
dependencies { implementation "androidx.navigation:navigation-runtime-ktx:2.8.4" implementation "androidx.navigation:navigation-fragment-ktx:2.8.4" implementation "androidx.navigation:navigation-ui-ktx:2.8.4" }
Kotlin
dependencies { implementation("androidx.navigation:navigation-runtime-ktx:2.8.4") implementation("androidx.navigation:navigation-fragment-ktx:2.8.4") implementation("androidx.navigation:navigation-ui-ktx:2.8.4") }
אפשר להשתמש בפונקציות התוסף ובהענקת גישה למאפיינים כדי לגשת לארגומנטים של יעד ולנווט ליעדי מודעות, כפי שמתואר בדוגמה הבאה:
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
של האפליקציה:
מגניב
dependencies { implementation "androidx.palette:palette-ktx:1.0.0" }
Kotlin
dependencies { implementation("androidx.palette:palette-ktx:1.0.0") }
לדוגמה, כשעובדים עם מכונה של Palette
, אפשר לאחזר את selected
swatch עבור target
נתון באמצעות אופרטור get ([ ]
):
val palette = Palette.from(bitmap).generate()
val swatch = palette[target]
Reactive Streams KTX
מודול KTX של Reactive Streams מאפשר ליצור מקור ReactiveStreams
של שידור LiveData
שניתן לצפות בו.
כדי לכלול את המודול הזה, מוסיפים את הנתונים הבאים לקובץ build.gradle
של האפליקציה:
מגניב
dependencies { implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:2.8.7" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:2.8.7") }
לדוגמה, נניח שיש מסד נתונים עם רשימה קטנה של משתמשים. באפליקציה, אתם מעמיסים את מסד הנתונים בזיכרון ולאחר מכן מציגים את נתוני המשתמשים בממשק המשתמש. כדי לעשות זאת, אפשר להשתמש ב-RxJava.
רכיב Jetpack Room
יכול לאחזר את רשימת המשתמשים כ-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 מוסיפים תמיכה ב-coroutines לעסקאות של מסדי נתונים.
כדי להשתמש במודול הזה, מוסיפים את הקוד הבא לקובץ build.gradle
של האפליקציה:
מגניב
dependencies { implementation "androidx.room:room-ktx:2.6.1" }
Kotlin
dependencies { implementation("androidx.room:room-ktx:2.6.1") }
ריכזנו כאן כמה דוגמאות שבהן Room משתמש עכשיו ב-coroutines. בדוגמה הראשונה נעשה שימוש בפונקציה suspend
כדי להחזיר רשימה של אובייקטים מסוג User
, ובדוגמה השנייה נעשה שימוש ב-Flow
של Kotlin כדי להחזיר את רשימת ה-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
של האפליקציה:
מגניב
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
. האירוע CoroutineScope
מקושר ל-Dispatchers.Main
ויוסר באופן אוטומטי כשה-ViewModel
יימחק. אפשר להשתמש ב-viewModelScope()
במקום ליצור היקף חדש לכל ViewModel
.
כדי לכלול את המודול הזה, מוסיפים את הנתונים הבאים לקובץ build.gradle
של האפליקציה:
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.5" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.5") }
לדוגמה, הפונקציה 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 מספק תמיכה ברמה הגבוהה ביותר ב-coroutines.
כדי לכלול את המודול הזה, מוסיפים את הנתונים הבאים לקובץ build.gradle
של האפליקציה:
מגניב
dependencies { implementation "androidx.work:work-runtime-ktx:2.9.1" }
Kotlin
dependencies { implementation("androidx.work:work-runtime-ktx:2.9.1") }
במקום להרחיב את Worker
, עכשיו אפשר להרחיב את CoroutineWorker
, שיש לו ממשק API שונה במקצת. לדוגמה, אם רוצים ליצור 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 יש גם פונקציות הרחבה ל-Operations
ול-ListenableFutures
להשהיית רצף הפעולות הנוכחי.
דוגמה להשעיה של הערך Operation
שמוחזר על ידי enqueue()
:
// Inside of a coroutine...
// Run async operation and suspend until completed.
WorkManager.getInstance()
.beginWith(longWorkRequest)
.enqueue().await()
// Resume after work completes...
מודולים אחרים של KTX
אפשר גם לכלול מודולים נוספים של KTX שנמצאים מחוץ ל-AndroidX.
Firebase KTX
לחלק מ-SDK של Firebase ל-Android יש ספריות תוספים של Kotlin שמאפשרות לכתוב קוד Kotlin לפי המוסכמות כשמשתמשים ב-Firebase באפליקציה. למידע נוסף, אפשר לעיין בנושאים הבאים:
Google Maps Platform KTX
יש תוספים של KTX שזמינים ל-SDK של פלטפורמת מפות Google ל-Android, שמאפשרים לכם ליהנות מכמה תכונות של שפת Kotlin, כמו פונקציות הרחבה, פרמטרים עם שם וארגומנטים שמוגדרים כברירת מחדל, הצהרות על ניתוח מבנה ו-coroutines. מידע נוסף זמין בנושאים הבאים:
Play Core KTX
Play Core KTX מוסיף תמיכה ב-coroutines של Kotlin לבקשות חד-פעמיות וב-Flow למעקב אחר עדכוני סטטוס, על ידי הוספת פונקציות תוסף ל-SplitInstallManager
ול-AppUpdateManager
בספריית Play Core.
כדי לכלול את המודול הזה, מוסיפים את הנתונים הבאים לקובץ 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.