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 بتطبيق التغييرات بشكل شامل.

في ما يلي مثال على إحدى وظائف 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 لمشروعك:

رائع

repositories {
    google()
}

Kotlin

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 الخاص بتطبيقك:

رائع

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

Kotlin

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

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

مجموعة KTX

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

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

رائع

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

Kotlin

dependencies {
    implementation("androidx.collection:collection-ktx:1.4.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

جزء KTX

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

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

رائع

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

Kotlin

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

باستخدام وحدة Fragment KTX، يمكنك تبسيط المعاملات المجزأة باستخدام ملفات lambdas، على سبيل المثال:

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 الخاص بتطبيقك:

رائع

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

Kotlin

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

ملف KTX لبيانات LiveData

عند استخدام LiveData، قد تحتاج إلى حساب القيم بشكل غير متزامن. على سبيل المثال، قد ترغب في استرداد تفضيلات المستخدم وعرضها في واجهة المستخدم لديك. في هذه الحالات، توفر LiveData KTX دالة إنشاء liveData تستدعي الدالة suspend وتعرض النتيجة ككائن LiveData.

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

رائع

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

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.7.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 الخاص بتطبيقك:

رائع

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

Kotlin

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

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

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 الخاص بتطبيقك:

رائع

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]

مجموعات KTX للبث المباشر

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

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

Groovy

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

Kotlin

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

كمثال، لنفترض وجود قاعدة بيانات بها قائمة صغيرة من المستخدمين. في تطبيقك، تقوم بتحميل قاعدة البيانات في الذاكرة ثم عرض بيانات المستخدم في واجهة المستخدم لديك. لتحقيق ذلك، يمكنك استخدام RxJava. يمكن لمكوِّن Jetpack في Room استرداد قائمة المستخدمين على أنها Flowable. في هذا السيناريو، يجب عليك أيضًا إدارة اشتراك ناشر Rx طوال عمر الجزء أو النشاط.

مع ذلك، يمكنك الاستفادة من RxJava من خلال LiveDataReactiveStreams ومجموعة كبيرة من عوامل التشغيل وإمكانيات جدولة العمل مع العمل ببساطة في LiveData، كما هو موضح في المثال التالي:

val fun getUsersLiveData() : LiveData<List<User>> {
    val users: Flowable<List<User>> = dao.findUsers()
    return LiveDataReactiveStreams.fromPublisher(users)
}

غرفة KTX

أما إضافات الغرف، فتشمل كل ما سبق فضلاً عن دعم كورروتيني لمعاملات قاعدة البيانات.

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

رائع

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

Kotlin

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 الخاص بتطبيقك:

رائع

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

Kotlin

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

في ما يلي مثال على استخدام الإضافة transaction لإجراء معاملة في قاعدة البيانات:

db.transaction {
    // insert data
}

عرض طراز KTX

توفّر مكتبة ViewModel KTX دالة viewModelScope() التي تسهّل تشغيل coroutines من ViewModel. يرتبط CoroutineScope بالعنوان Dispatchers.Main ويتم إلغاؤه تلقائيًا عند محو ViewModel. يمكنك استخدام viewModelScope() بدلاً من إنشاء نطاق جديد لكل ViewModel.

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

رائع

dependencies {
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0"
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.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 الخاص بتطبيقك:

رائع

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

Kotlin

dependencies {
    implementation("androidx.work:work-runtime-ktx:2.9.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 في تطبيقك. ولمزيد من المعلومات، يُرجى الاطّلاع على المواضيع التالية:

منصة خرائط Google KTX

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

تشغيل Core KTX

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

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