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 מספק תוספים לספריות נפוצות שהן חלק מ-framework של 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
KTX של מחזור חיים מגדיר LifecycleScope
לכל אובייקט Lifecycle
. כל קורוטין שמופעלת בהיקף הזה מבוטל כשה-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 עם רכיבי ארכיטקטורה.
KTX ניווט
לכל רכיב בספריית הניווט יש גרסה משלו של KTX שמתאימה את ה-API כך שיהיה תמציתי יותר ותואמת ל-Kotlin.
כדי לכלול את המודולים האלה, מוסיפים את הנתונים הבאים לקובץ build.gradle
של האפליקציה:
מגניב
dependencies { implementation "androidx.navigation:navigation-runtime-ktx:2.8.1" implementation "androidx.navigation:navigation-fragment-ktx:2.8.1" implementation "androidx.navigation:navigation-ui-ktx:2.8.1" }
Kotlin
dependencies { implementation("androidx.navigation:navigation-runtime-ktx:2.8.1") implementation("androidx.navigation:navigation-fragment-ktx:2.8.1") implementation("androidx.navigation:navigation-ui-ktx:2.8.1") }
אפשר להשתמש בפונקציות התוסף ובהענקת גישה למאפיינים כדי לגשת לארגומנטים של יעד ולנווט ליעדי מודעות, כפי שמתואר בדוגמה הבאה:
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)
}
}
...
}
פלטת 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)
}
חדר 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 בטרנזקציות, וכך לא משתמשים הרבה בקודים (boilerplate).
כדי להשתמש במודול הזה, צריך להוסיף את הקוד הבא לקובץ 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
תוכלו לעיין במאמר Threading ב-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.