‫Android KTX   هي جزء من Android Jetpack.

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

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

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

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

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

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

Kotlin

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

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

مجموعة 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")
}

تستفيد إضافات المجموعات من التحميل الزائد لمشغّل 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 في تطبيقك:

Groovy

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

Kotlin

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

باستخدام وحدة 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 في تطبيقك:

Groovy

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

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.11.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.11.0"
}

Kotlin

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

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

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

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

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

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

Groovy

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

Kotlin

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

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

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.11.0"
}

Kotlin

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

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

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

Groovy

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

Kotlin

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

في ما يلي بعض الأمثلة على استخدام 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 في المعاملات، مما يلغي الكثير من الرموز البرمجية النموذجية.

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

Groovy

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

Kotlin

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

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

Kotlin

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

على سبيل المثال، تطلق دالة viewModelScope() التالية دالة coroutine تُجري طلب شبكة في سلسلة محادثات في الخلفية. تتولى المكتبة جميع عمليات الإعداد ومحو النطاق المقابل:

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 في تطبيقك:

أنيق

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

Kotlin

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

بدلاً من تمديد 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، يُرجى الاطّلاع على 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

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

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

تتوفّر إضافات KTX لحِزم تطوير البرامج (SDK) الخاصة بـ "منصة خرائط Google" على Android، والتي تتيح لك الاستفادة من العديد من ميزات لغة 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.