Android KTX חלק מ-Android Jetpack.
Android KTX היא קבוצה של תוספי Kotlin שנכללים ב-Android Jetpack ובספריות אחרות של Android. תוספי KTX מספקים קוד Kotlin תמציתי, אידיומטי ל-Jetpack, לפלטפורמת Android ולממשקי API אחרים. לשם כך, התוספים האלה מסתמכים על כמה תכונות של שפת Kotlin, כולל התכונות הבאות:
- פונקציות של תוספים
- מאפייני התוסף
- Lambdas
- פרמטרים עם שם
- ערכי ברירת מחדל של פרמטרים
- שגרות משנה (coroutines)
לדוגמה, כשעובדים עם SharedPreferences
, צריך ליצור הרשאת עריכה לפני שאפשר לבצע שינויים בנתוני ההעדפות. בסיום העריכה, צריך גם להחיל או לאשר את השינויים, כמו בדוגמה הבאה:
sharedPreferences
.edit() // create an Editor
.putBoolean("key", value)
.apply() // write to disk asynchronously
ביטויים מסוג Lambda ב-Kotlin מתאימים מאוד לתרחיש השימוש הזה. הם מאפשרים לכם להשתמש בגישה תמציתית יותר על ידי העברת בלוק קוד לביצוע אחרי יצירת העורך, ביצוע הקוד ואז מתן אפשרות ל-API של SharedPreferences
להחיל את השינויים באופן אטומי.
דוגמה לאחת מהפונקציות של Android KTX Core,
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
lambda היא בעצמה פונקציית הרחבה אנונימית של SharedPreferences.Editor
שמחזירה את Unit
, כפי שמצוין בחתימה שלה. לכן, בתוך הבלוק
אפשר לבצע את העבודה ישירות על SharedPreferences.Editor
.
לבסוף, החתימה SharedPreferences.edit()
מכילה את מילת המפתח inline
.
מילת המפתח הזו אומרת לקומפיילר של Kotlin שהוא צריך להעתיק ולהדביק (או להטמיע) את בייטקוד המהדר של הפונקציה בכל פעם שמשתמשים בפונקציה.
כך נמנעים מהתקורה של יצירת מופע חדש של מחלקה לכל action
בכל פעם שהפונקציה הזו מופעלת.
הדפוס הזה של העברת קוד באמצעות ביטויי למדה, החלת ברירות מחדל הגיוניות שאפשר לבטל והוספת ההתנהגויות האלה לממשקי API קיימים באמצעות inline
פונקציות הרחבה, הוא אופייני לשיפורים שמסופקים על ידי ספריית Android KTX.
שימוש ב-Android KTX בפרויקט
כדי להתחיל להשתמש ב-Android KTX, מוסיפים את התלות הבאה לקובץ build.gradle
של הפרויקט:
מגניב
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
של האפליקציה:
Groovy
dependencies { implementation "androidx.core:core-ktx:1.16.0" }
Kotlin
dependencies { implementation("androidx.core:core-ktx:1.16.0") }
זו רשימה של החבילות שנכללות במודול 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
תוספי האוסף מכילים פונקציות עזר לעבודה עם ספריות אוסף חסכוניות בזיכרון של Android, כולל ArrayMap
, LongSparseArray
, LruCache
ועוד.
כדי להשתמש במודול הזה, מוסיפים את השורות הבאות לקובץ build.gradle
של האפליקציה:
Groovy
dependencies { implementation "androidx.collection:collection-ktx:1.5.0" }
Kotlin
dependencies { implementation("androidx.collection:collection-ktx:1.5.0") }
תוספי אוסף משתמשים בהעמסת אופרטורים של 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 מספק מספר תוספים שמפשטים את Fragment API.
כדי לכלול את המודול הזה, מוסיפים את השורות הבאות לקובץ build.gradle
של האפליקציה:
מגניב
dependencies { implementation "androidx.fragment:fragment-ktx:1.8.8" }
Kotlin
dependencies { implementation("androidx.fragment:fragment-ktx:1.8.8") }
בעזרת מודול Fragment KTX, אפשר לפשט את טרנזקציות הפרגמנטים באמצעות למבדות, למשל:
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
. כל קורוטינה
שמופעלת בהיקף הזה מבוטלת כשהאובייקט Lifecycle
מושמד. אפשר לגשת אל CoroutineScope
של Lifecycle
באמצעות המאפיינים lifecycle.coroutineScope
או lifecycleOwner.lifecycleScope
.
כדי לכלול את המודול הזה, מוסיפים את השורות הבאות לקובץ build.gradle
של האפליקציה:
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.9.1" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.9.1") }
בדוגמה הבאה אפשר לראות איך משתמשים ב-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 מספקת פונקציית יצירה liveData
שקוראת לפונקציה suspend
ומציגה את התוצאה כאובייקט LiveData
.
כדי לכלול את המודול הזה, מוסיפים את השורות הבאות לקובץ build.gradle
של האפליקציה:
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.9.1" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.9.1") }
בדוגמה הבאה, loadUser()
היא פונקציית השהיה שהוגדרה במקום אחר.
אפשר להשתמש בפונקציית ה-builder liveData
כדי להפעיל את loadUser()
באופן אסינכרוני, ואז להשתמש ב-emit()
כדי להציג את התוצאה:
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
מידע נוסף על שימוש בשגרות משנה עם LiveData
זמין במאמר בנושא שימוש בשגרות משנה ב-Kotlin עם רכיבי ארכיטקטורה.
Navigation KTX
לכל רכיב בספריית הניווט יש גרסת KTX משלו, שמתאימה את ה-API כך שיהיה תמציתי יותר ויתאים יותר ל-Kotlin.
כדי לכלול את המודולים האלה, מוסיפים את השורות הבאות לקובץ build.gradle
של האפליקציה:
Groovy
dependencies { implementation "androidx.navigation:navigation-runtime-ktx:2.9.1" implementation "androidx.navigation:navigation-fragment-ktx:2.9.1" implementation "androidx.navigation:navigation-ui-ktx:2.9.1" }
Kotlin
dependencies { implementation("androidx.navigation:navigation-runtime-ktx:2.9.1") implementation("androidx.navigation:navigation-fragment-ktx:2.9.1") implementation("androidx.navigation:navigation-ui-ktx:2.9.1") }
כדי לגשת לארגומנטים של היעד ולעבור ליעדים, משתמשים בפונקציות ההרחבה ובמאפיין delegation, כמו בדוגמה הבאה:
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
של target
מסוים באמצעות האופרטור get ([ ]
):
val palette = Palette.from(bitmap).generate()
val swatch = palette[target]
Reactive Streams KTX
מודול Reactive Streams KTX מאפשר ליצור זרם LiveData
ניתן לצפייה מReactiveStreams
בעל תוכן דיגיטלי.
כדי לכלול את המודול הזה, מוסיפים את השורות הבאות לקובץ build.gradle
של האפליקציה:
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:2.9.1" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:2.9.1") }
לדוגמה, נניח שיש מסד נתונים עם רשימה קטנה של משתמשים. באפליקציה, אתם טוענים את מסד הנתונים לזיכרון ואז מציגים את נתוני המשתמש בממשק המשתמש. כדי לעשות את זה, אפשר להשתמש ב-RxJava.
רכיב Jetpack Room
יכול לאחזר את רשימת המשתמשים כ-Flowable
. בתרחיש הזה, אתם צריכים גם לנהל את המינוי של Rx
publisher לאורך כל משך החיים של הפעילות או של הקטע.
עם זאת, בעזרת 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.7.2" }
Kotlin
dependencies { implementation("androidx.room:room-ktx:2.7.2") }
הנה כמה דוגמאות לשימוש בקורוטינות ב-Room: בדוגמה הראשונה נעשה שימוש בפונקציה 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.5.2" }
Kotlin
dependencies { implementation("androidx.sqlite:sqlite-ktx:2.5.2") }
דוגמה לשימוש בתוסף transaction
כדי לבצע טרנזקציה במסד נתונים:
db.transaction {
// insert data
}
ViewModel KTX
ספריית ViewModel KTX מספקת פונקציה viewModelScope()
שמקלה על הפעלת coroutines מ-ViewModel
. CoroutineScope
משויך ל-Dispatchers.Main
ומתבטל באופן אוטומטי
כשמנקים את ViewModel
. אפשר להשתמש ב-viewModelScope()
במקום ליצור היקף חדש לכל ViewModel
.
כדי לכלול את המודול הזה, מוסיפים את השורות הבאות לקובץ build.gradle
של האפליקציה:
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.1" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.1") }
לדוגמה, הפונקציה 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.10.2" }
Kotlin
dependencies { implementation("androidx.work:work-runtime-ktx:2.10.2") }
במקום להשתמש ב-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 in 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
חלק מ-Firebase SDKs ל-Android כוללים ספריות הרחבה של Kotlin שמאפשרות לכתוב קוד Kotlin אידיומטי כשמשתמשים ב-Firebase באפליקציה. מידע נוסף זמין בנושאים הבאים:
Google Maps Platform KTX
יש הרחבות KTX זמינות לערכות SDK של Android בפלטפורמה של מפות Google, שמאפשרות לכם ליהנות מכמה תכונות של שפת Kotlin, כמו פונקציות הרחבה, פרמטרים עם שמות וארגומנטים שמוגדרים כברירת מחדל, הצהרות על פירוק למשתנים וקורוטינות. מידע נוסף זמין בנושאים הבאים:
Play Core KTX
ספריית Play Core KTX מוסיפה תמיכה ב-Kotlin coroutines לבקשות חד-פעמיות וב-Flow למעקב אחרי עדכוני סטטוס, על ידי הוספת פונקציות הרחבה ל-SplitInstallManager
ול-AppUpdateManager
בספריית Play Core.
כדי לכלול את המודול הזה, מוסיפים את השורות הבאות לקובץ build.gradle
של האפליקציה:
מגניב
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.