‫Android KTX   جزء من Android Jetpack.

‫Android KTX هي مجموعة من إضافات Kotlin المضمّنة في Android Jetpack ومكتبات Android الأخرى. توفّر إضافات KTX لغة Kotlin موجزة ومناسبة لـ Jetpack ونظام Android الأساسي وواجهات برمجة التطبيقات الأخرى. لتحقيق ذلك، تستفيد هذه الإضافات من عدة ميزات في لغة Kotlin، بما في ذلك ما يلي:

  • دوال الإضافة
  • خصائص الإضافة
  • تعبيرات لامدا
  • المَعلمات المُسمّاة
  • القيم التلقائية للمَعلمات
  • الكوروتينات

على سبيل المثال، عند استخدام SharedPreferences، عليك إنشاء أداة تعديل قبل إجراء تعديلات على بيانات الإعدادات المفضّلة. عليك أيضًا تطبيق هذه التغييرات أو إرسالها عند الانتهاء من التعديل، كما هو موضّح في المثال التالي:

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

تعبيرات لامدا في Kotlin مناسبة تمامًا لحالة الاستخدام هذه. تتيح لك هذه التعبيرات اتّباع نهج أكثر إيجازًا من خلال تمرير مجموعة من التعليمات البرمجية لتنفيذها بعد إنشاء أداة التعديل، ما يسمح بتنفيذ التعليمات البرمجية، ثم السماح لواجهة برمجة التطبيقات SharedPreferences بتطبيق التغييرات بشكل غير قابل للتجزئة.

في ما يلي مثال على إحدى دوال 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 هو في حد ذاته دالة إضافة مجهولة على SharedPreferences.Editor تعرض Unit، كما هو موضّح في توقيعها. لهذا السبب، يمكنك إجراء العمل مباشرةً على SharedPreferences.Editor داخل الـ block.

أخيرًا، يحتوي توقيع SharedPreferences.edit() على الكلمة الرئيسية inline. تخبر هذه الكلمة الرئيسية برنامج ترجمة Kotlin بأنّه يجب نسخ ولصق (أو تضمين) رمز البايت المُجمَّع للدالة في كل مرة يتم فيها استخدام الدالة. يؤدي ذلك إلى تجنُّب النفقات العامة لإنشاء فئة جديدة لكل action في كل مرة يتم فيها استدعاء هذه الدالة.

إنّ نمط تمرير التعليمات البرمجية باستخدام تعبيرات لامدا، وتطبيق الإعدادات التلقائية المعقولة التي يمكن إلغاؤها، وإضافة هذه السلوكيات إلى واجهات برمجة التطبيقات الحالية باستخدام دوال الإضافة inline هو نمط التحسينات التي توفّرها مكتبة Android KTX.

استخدام Android KTX في مشروعك

لبدء استخدام Android KTX، أضِف التبعية التالية إلى ملف build.gradle الخاص بمشروعك:

أنيق

repositories {
    google()
}

Kotlin

repositories {
    google()
}

وحدات AndroidX

يتم تنظيم Android KTX في وحدات، تحتوي كل وحدة على حزمة واحدة أو أكثر.

عليك تضمين تبعية لكل عنصر من عناصر الوحدة في ملف build.gradle الخاص بتطبيقك. تذكَّر إلحاق رقم الإصدار بالعنصر. يمكنك العثور على أرقام أحدث الإصدارات في القسم المقابل لكل عنصر في هذا الموضوع.

يحتوي Android KTX على وحدة أساسية واحدة توفّر إضافات Kotlin لواجهات برمجة التطبيقات الشائعة في إطار العمل وعدة إضافات خاصة بمجالات معيّنة.

باستثناء الوحدة الأساسية، تحلّ جميع عناصر وحدة 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.18.0"
}

Kotlin

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

في ما يلي قائمة بالحِزم المضمّنة في وحدة Core KTX:

‫Collection KTX

تحتوي إضافات Collection على دوال مساعدة للتعامل مع مكتبات مجموعات Android الفعّالة من حيث استخدام الذاكرة، بما في ذلك ArrayMap وLongSparseArray وLruCache وغيرها.

لاستخدام هذه الوحدة، أضِف ما يلي إلى ملف build.gradle الخاص بتطبيقك:

رائع

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

Kotlin

dependencies {
    implementation("androidx.collection:collection-ktx:1.6.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 عددًا من الإضافات لتبسيط واجهة برمجة التطبيقات الخاصة بالجزء.

لتضمين هذه الوحدة، أضِف ما يلي إلى ملف build.gradle الخاص بتطبيقك:

Groovy

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

Kotlin

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

باستخدام وحدة 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.10.0"
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.10.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، قد تحتاج إلى حساب القيم بشكل غير متزامن. على سبيل المثال، قد تريد استرداد الإعدادات المفضّلة للمستخدم وعرضها في واجهة المستخدم. في هذه الحالات، توفّر LiveData KTX دالة إنشاء liveData تستدعي دالة suspend وتعرض النتيجة كعنصر LiveData.

لتضمين هذه الوحدة، أضِف ما يلي إلى ملف build.gradle الخاص بتطبيقك:

Groovy

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

Kotlin

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

في المثال التالي، loadUser() هي دالة تعليق تم تعريفها في مكان آخر. يمكنك استخدام دالة الإنشاء liveData لاستدعاء loadUser() بشكل غير متزامن، ثم استخدام emit() لعرض النتيجة:

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

لمزيد من المعلومات حول استخدام الكوروتينات مع LiveData، يُرجى الاطّلاع على مقالة استخدام كوروتينات Kotlin مع مكوّنات البنية.

يحتوي كل مكوّن من مكتبة Navigation على إصدار KTX خاص به يكيّف واجهة برمجة التطبيقات لتكون أكثر إيجازًا ومناسبة للغة Kotlin.

لتضمين هذه الوحدات، أضِف ما يلي إلى ملف build.gradle الخاص بتطبيقك:

Groovy

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

Kotlin

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

استخدِم دوال الإضافة وتفويض الخصائص للوصول إلى وسيطات الوجهة والانتقال إلى الوجهات، كما هو موضّح في المثال التالي:

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، يمكنك استرداد عيّنة 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.10.0"
}

Kotlin

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

على سبيل المثال، لنفترض قاعدة بيانات تحتوي على قائمة صغيرة من المستخدمين. في تطبيقك، يمكنك تحميل قاعدة البيانات في الذاكرة ثم عرض بيانات المستخدم في واجهة المستخدم. لتحقيق ذلك، يمكنك استخدام 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.8.4"
}

Kotlin

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

في ما يلي مثالان تستخدم فيهما Room الآن الكوروتينات. يستخدم المثال الأول دالة suspend لعرض قائمة بعناصر User، بينما يستخدم المثال الثاني `Flow` في KotlinFlow لعرض قائمة 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.6.2"
}

Kotlin

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

في ما يلي مثال على استخدام إضافة 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.10.0"
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.10.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.11.2"
}

Kotlin

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

بدلاً من توسيع Worker، يمكنك الآن توسيع 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 أيضًا دوال إضافة إلى 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 SDK لنظام Android على مكتبات إضافات Kotlin تتيح لك كتابة تعليمات برمجية مناسبة للغة Kotlin عند استخدام Firebase في تطبيقك. لمزيد من المعلومات، يُرجى الاطّلاع على المواضيع التالية:

‫منصة خرائط Google KTX

تتوفّر إضافات KTX لحِزم حزمة تطوير البرامج (SDK) لنظام التشغيل Android لمنصة خرائط Google التي تتيح لك الاستفادة من عدة ميزات في لغة Kotlin، مثل دوال الإضافة والمَعلمات المُسمّاة والوسيطات التلقائية وإزالة البنية والكوروتينات. لمزيد من المعلومات، يُرجى الاطّلاع على المواضيع التالية:

مكتبة Play الأساسية KTX

تضيف Play Core KTX دعمًا لكوروتينات Kotlin للطلبات لمرة واحدة وFlow لمراقبة آخر الأخبار عن حالات التعديل من خلال إضافة دوال إضافة إلى SplitInstallManager وAppUpdateManager في مكتبة Play الأساسية.

لتضمين هذه الوحدة، أضِف ما يلي إلى ملف 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.