‫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) }

يمكن للمتصل اختيار إكمال التغييرات أو تطبيقها. إنّ دالة action lambda هي نفسها دالة إضافة مجهولة المصدر في SharedPreferences.Editor تعرض Unit، كما هو موضّح في توقيعها. لهذا السبب، يمكنك تنفيذ العمل مباشرةً على SharedPreferences.Editor داخل الحظر.

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

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

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

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

Groovy

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

رائع

dependencies {
    implementation "androidx.core:core-ktx:1.16.0"
}

Kotlin

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

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

Collection KTX

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

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

رائع

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 عددًا من الدوال الإضافية لتبسيط واجهة برمجة التطبيقات الخاصة بالتقسيم.

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

Groovy

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

Kotlin

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

باستخدام وحدة 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. يتم إلغاء أي إجراء روتيني متزامن تم إطلاقه في هذا النطاق عند إتلاف Lifecycle. يمكنك الوصول إلى CoroutineScope الخاص بـ Lifecycle باستخدام السمتَين lifecycle.coroutineScope أو lifecycleOwner.lifecycleScope.

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

رائع

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() هي دالة تعليق معرَّفة في مكان آخر. يمكنك استخدام دالة الإنشاء 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.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")
}

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

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

رائع

dependencies {
    implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:2.9.1"
}

Kotlin

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

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

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

Groovy

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() التي تسهّل تشغيل الروتينات الفرعية من ViewModel. يرتبط CoroutineScope بالجهاز Dispatchers.Main ويتم إلغاؤه تلقائيًا عند محو بيانات ViewModel. يمكنك استخدام viewModelScope() بدلاً من إنشاء نطاق جديد لكل ViewModel.

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

رائع

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

Groovy

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

Kotlin

dependencies {
    implementation("androidx.work:work-runtime-ktx:2.10.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

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

Google Maps Platform KTX

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

Play Core KTX

تضيف Play Core KTX إمكانية استخدام إجراءات روتينية في 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.