‫Android KTX   جزء من Android Jetpack.

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

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

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

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

وتتناسب لغة Kotlin lambdas بشكل مثالي مع حالة الاستخدام هذه. تتيح لك هذه الأدوات اتّباع أسلوبٍ أكثر إيجازًا من خلال تمرير مجموعة من الرموز البرمجية لتنفيذها بعد إنشاء المحرِّر، والسماح بتنفيذ الرمز البرمجي، ثم السماح لواجهة 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) }

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

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

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

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

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

رائعKotlin
repositories {
    google()
}
repositories {
    google()
}

وحدات AndroidX

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

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

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

باستثناء الوحدة الأساسية، تستبدل جميع عناصر وحدة KTX التبعية الأساسية لـ Java في ملف build.gradle. على سبيل المثال، يمكنك استبدال تبعية androidx.fragment:fragment بأحد تبعيات androidx.fragment:fragment-ktx. تساعد هذه البنية في إدارة الإصدارات بشكل أفضل ولا تضيف متطلبات إضافية لبيان التبعية.

حزمة KTX الأساسية

توفّر وحدة Core KTX إضافات للمكتبات الشائعة التي تشكل جزءًا من إطار عمل Android. لا تحتوي هذه المكتبات على تبعيات مستندة إلى Java عليك إضافتها إلى build.gradle.

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

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

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

مجموعة KTX

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

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

GroovyKotlin
dependencies {
    implementation "androidx.collection:collection-ktx:1.4.5"
}
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

جزء من KTX

توفّر وحدة Fragment KTX عددًا من الإضافات لتبسيط واجهة برمجة التطبيقات Fragment API.

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

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

باستخدام وحدة 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>()

دورة حياة KTX

تحدِّد حزمة KTX لدورة الحياة LifecycleScope لكل عنصر Lifecycle. يتم إلغاء أي دالة معالجة متزامنة تم تشغيلها في هذا النطاق عند إتلاف Lifecycle. يمكنك الوصول إلى CoroutineScope من Lifecycle باستخدام السمتَين lifecycle.coroutineScope أو lifecycleOwner.lifecycleScope.

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

GroovyKotlin
dependencies {
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.7"
}
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 دالة liveData لإنشاء liveData تُشغِّل دالة suspend وتعرض النتيجة كعنصر LiveData.

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

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

في المثال التالي، 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 في تطبيقك:

GroovyKotlin
dependencies {
    implementation "androidx.navigation:navigation-runtime-ktx:2.8.8"
    implementation "androidx.navigation:navigation-fragment-ktx:2.8.8"
    implementation "androidx.navigation:navigation-ui-ktx:2.8.8"
}
dependencies {
    implementation("androidx.navigation:navigation-runtime-ktx:2.8.8")
    implementation("androidx.navigation:navigation-fragment-ktx:2.8.8")
    implementation("androidx.navigation:navigation-ui-ktx:2.8.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)
            }
     }
     ...

}

لوحة ألوان KTX

تقدّم وحدة Palette KTX دعمًا لأسلوب Kotlin في العمل مع لوحات الألوان.

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

GroovyKotlin
dependencies {
    implementation "androidx.palette:palette-ktx:1.0.0"
}
dependencies {
    implementation("androidx.palette:palette-ktx:1.0.0")
}

على سبيل المثال، عند العمل مع مثيل Palette، يمكنك استرداد ملف التمويه selected لقيمة target معيّنة باستخدام عامل التشغيل get ([ ]):

val palette = Palette.from(bitmap).generate()
val swatch = palette[target]

فيديوهات KTX التفاعلية

تتيح لك وحدة Reactive Streams KTX إنشاء بث LiveData قابل للرصد من ناشر ReactiveStreams.

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

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

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

غرفة KTX

توفّر إضافات الغرف إمكانية استخدام وحدات معالجة المهام المتزامنة لمعاملات قاعدة البيانات.

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

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

في ما يلي بعض الأمثلة التي تستخدم فيها 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 في تطبيقك:

GroovyKotlin
dependencies {
    implementation "androidx.sqlite:sqlite-ktx:2.4.0"
}
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 في تطبيقك:

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

على سبيل المثال، تبدأ الدالة 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 في تطبيقك:

GroovyKotlin
dependencies {
    implementation "androidx.work:work-runtime-ktx:2.10.0"
}
dependencies {
    implementation("androidx.work:work-runtime-ktx:2.10.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، اطّلِع على المعالجة المتعدّدة في CoroutineWorker.

تضيف حزمة WorkManager KTX أيضًا وظائف إضافة إلى Operations و ListenableFutures لتعليق دالة coroutine الحالية.

في ما يلي مثال على تعليق القيمة 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 في "نظام خرائط Google" والتي تتيح لك الاستفادة من العديد من ميزات لغة Kotlin، مثل دوال الإضافات والمَعلمات المُسمّاة والوسيطات التلقائية وتعريفات التدمير والكوروتينات. لمزيد من المعلومات، اطّلِع على المواضيع التالية:

حزمة KTX لـ Play Core

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

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

GroovyKotlin
dependencies {
    implementation "com.google.android.play:core-ktx:1.8.1"
}
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.