‫Android Kotlin Fundamentals 06.3: استخدام LiveData للتحكّم في حالات الأزرار

هذا الدرس التطبيقي حول الترميز هو جزء من دورة "أساسيات Android Kotlin". يمكنك تحقيق أقصى استفادة من هذه الدورة التدريبية إذا اتبعت ترتيب الخطوات في دروس البرمجة. يتم إدراج جميع الدروس التطبيقية حول الترميز الخاصة بالدورة التدريبية في الصفحة المقصودة للدروس التطبيقية حول الترميز في دورة Android Kotlin Fundamentals.

مقدمة

يلخّص هذا الدرس التطبيقي حول الترميز كيفية استخدام ViewModel والتقسيمات معًا لتنفيذ عملية التنقّل. تذكَّر أنّ الهدف هو وضع منطق وقت التنقّل في ViewModel، ولكن حدِّد المسارات في الأجزاء وملف التنقّل. لتحقيق هذا الهدف، يمكنك استخدام نماذج العرض والتقسيمات وLiveData والمراقبين.

ينتهي الدرس العملي بعرض طريقة ذكية لتتبُّع حالات الأزرار بأقل قدر من الرموز البرمجية، بحيث يتم تفعيل كل زرّ ويمكن النقر عليه فقط عندما يكون من المنطقي أن ينقر المستخدِم على هذا الزرّ.

ما يجب معرفته

يجب أن تكون على دراية بما يلي:

  • إنشاء واجهة مستخدم أساسية باستخدام نشاط وقِطع وعناصر عرض
  • التنقّل بين الأجزاء واستخدام safeArgs لنقل البيانات بين الأجزاء
  • عرض النماذج وعوامل إنشاء النماذج وعمليات التحويل وLiveData والمراقبين المرتبطين بها
  • كيفية إنشاء قاعدة بيانات Room وإنشاء عنصر الوصول إلى البيانات (DAO) وتحديد الكيانات
  • كيفية استخدام الروتينات الفرعية للتفاعلات مع قاعدة البيانات والمهام الأخرى التي تستغرق وقتًا طويلاً

أهداف الدورة التعليمية

  • كيفية تعديل سجلّ حالي لجودة النوم في قاعدة البيانات
  • كيفية استخدام LiveData لتتبُّع حالات الأزرار
  • كيفية عرض شريط معلومات استجابةً لحدث

الإجراءات التي ستنفذّها

  • وسِّع تطبيق TrackMySleepQuality لجمع تقييم الجودة وإضافة التقييم إلى قاعدة البيانات وعرض النتيجة.
  • استخدِم LiveData لتفعيل عرض شريط المعلومات.
  • استخدِم LiveData لتفعيل الأزرار وإيقافها.

في هذا الدرس البرمجي، ستنشئ واجهة المستخدم النهائية لتطبيق TrackMySleepQuality وتسجّل جودة النوم.

يحتوي التطبيق على شاشتَين، يتم تمثيلهما بلقطات، كما هو موضّح في الشكل أدناه.

تحتوي الشاشة الأولى، المعروضة على اليمين، على أزرار لبدء التتبُّع وإيقافه. تعرِض الشاشة جميع بيانات نوم المستخدم. يؤدي النقر على الزر محو إلى حذف جميع البيانات التي جمعها التطبيق للمستخدم نهائيًا.

الشاشة الثانية، المعروضة على اليسار، مخصّصة لاختيار تقييم لجودة النوم. في التطبيق، يتم تمثيل التقييم رقميًا. لأغراض التطوير، يعرض التطبيق رموز الوجوه وما يعادلها من أرقام.

يكون تدفّق المستخدم على النحو التالي:

  • يفتح المستخدم التطبيق وتظهر له شاشة تتبُّع النوم.
  • ينقر المستخدم على الزر بدء. تسجّل هذه السمة وقت البدء وتعرضه. يكون زر بدء غير مفعَّل، بينما يكون زر إيقاف مفعَّلاً.
  • ينقر المستخدم على الزر إيقاف. يتم تسجيل وقت الانتهاء وفتح شاشة جودة النوم.
  • يختار المستخدم رمزًا لجودة النوم. تنغلق الشاشة، وتعرض شاشة التتبُّع وقت انتهاء النوم وجودته. يكون زر إيقاف غير مفعَّل ويكون زر بدء مفعَّلاً. التطبيق جاهز للاستخدام في ليلة أخرى.
  • يتم تفعيل الزر محو عندما تكون هناك بيانات في قاعدة البيانات. عندما ينقر المستخدم على الزر محو، يتم محو جميع بياناته بدون رجعة، ولن تظهر الرسالة "هل أنت متأكد؟".

يستخدم هذا التطبيق بنية مبسطة، كما هو موضّح أدناه في سياق البنية الكاملة. يستخدم التطبيق المكوّنات التالية فقط:

  • وحدة التحكّم في واجهة المستخدم
  • عرض النموذج وLiveData
  • قاعدة بيانات Room

يفترض هذا الدرس التطبيقي حول الترميز أنّك تعرف كيفية تنفيذ التنقّل باستخدام الأجزاء وملف التنقّل. لتوفير الوقت، يتم توفير جزء كبير من هذا الرمز.

الخطوة 1: فحص الرمز

  1. للبدء، يمكنك مواصلة استخدام الرمز الخاص بك من نهاية آخر درس برمجة، أو تنزيل الرمز المُعد مسبقًا للمبتدئين.
  2. في رمز البداية، افحص SleepQualityFragment. تعمل هذه الفئة على توسيع التصميم والحصول على التطبيق وعرض binding.root.
  3. افتح navigation.xml في "محرِّر التصميم". يمكنك ملاحظة مسار تنقّل من SleepTrackerFragment إلى SleepQualityFragment، ثم العودة من SleepQualityFragment إلى SleepTrackerFragment.



  4. افحص الرمز بحثًا عن navigation.xml. على وجه الخصوص، ابحث عن <argument> باسم sleepNightKey.

    عندما ينتقل المستخدم من SleepTrackerFragment إلى SleepQualityFragment,، سيمرِّر التطبيق sleepNightKey إلى SleepQualityFragment لليلة التي يجب تعديلها.

الخطوة 2: إضافة أزرار التنقّل لتتبُّع جودة النوم

يتضمّن الرسم البياني للتنقّل المسارات من SleepTrackerFragment إلى SleepQualityFragment والعودة مرة أخرى. ومع ذلك، لم تتم كتابة رموز معالجات النقرات التي تنفّذ عملية التنقّل من جزء إلى آخر بعد. يمكنك إضافة هذا الرمز الآن في ViewModel.

في معالج النقرات، يمكنك ضبط LiveData يتغيّر عندما تريد أن ينتقل التطبيق إلى وجهة مختلفة. تراقب الفئة Fragment هذا LiveData. عندما تتغيّر البيانات، ينتقل الجزء إلى الوجهة ويُعلم نموذج العرض بأنّه قد انتهى، ما يؤدي إلى إعادة ضبط متغيّر الحالة.

  1. فتح "SleepTrackerViewModel" عليك إضافة أداة التنقّل حتى يتمكّن التطبيق من الانتقال إلى SleepQualityFragment لجمع تقييم الجودة عندما ينقر المستخدم على الزر إيقاف.
  2. في SleepTrackerViewModel، أنشئ LiveData يتغيّر عندما تريد أن ينتقل التطبيق إلى SleepQualityFragment. استخدِم التغليف لعرض نسخة قابلة للاسترداد من LiveData إلى ViewModel فقط.

    يمكنك وضع هذا الرمز في أي مكان في المستوى الأعلى من نص الصف.
private val _navigateToSleepQuality = MutableLiveData<SleepNight>()

val navigateToSleepQuality: LiveData<SleepNight>
   get() = _navigateToSleepQuality
  1. أضِف الدالة doneNavigating() التي تعيد ضبط المتغيّر الذي يؤدي إلى التنقّل.
fun doneNavigating() {
   _navigateToSleepQuality.value = null
}
  1. في معالج النقر على الزر إيقاف، onStopTracking()، ابدأ التنقّل إلى SleepQualityFragment. اضبط المتغيّر _navigateToSleepQuality في نهاية الدالة كآخر عنصر داخل كتلة launch{}. يُرجى العِلم أنّه تم ضبط هذه السمة على night. عندما يتضمّن هذا المتغيّر قيمة، ينتقل التطبيق إلى SleepQualityFragment، مع تمرير الليلة.
_navigateToSleepQuality.value = oldNight
  1. يجب أن يراقب SleepTrackerFragment _navigateToSleepQuality لكي يعرف التطبيق متى يجب الانتقال إلى صفحة أخرى. في SleepTrackerFragment، ضمن onCreateView()، أضِف مراقبًا إلى navigateToSleepQuality(). يُرجى العِلم أنّ عملية الاستيراد هذه غير واضحة، وعليك استيراد androidx.lifecycle.Observer.
sleepTrackerViewModel.navigateToSleepQuality.observe(this, Observer {
})

  1. داخل كتلة المراقب، انتقِل إلى رقم تعريف الليلة الحالية ومرِّره، ثم استدعِ doneNavigating(). إذا كان الاستيراد غامضًا، استورِد androidx.navigation.fragment.findNavController.
night ->
night?.let {
   this.findNavController().navigate(
           SleepTrackerFragmentDirections
                   .actionSleepTrackerFragmentToSleepQualityFragment(night.nightId))
   sleepTrackerViewModel.doneNavigating()
}
  1. أنشئ تطبيقك وشغِّله. انقر على بدء، ثم انقر على إيقاف، ما سينقلك إلى شاشة SleepQualityFragment. للرجوع، استخدِم زر الرجوع في النظام.

في هذه المهمة، عليك تسجيل جودة النوم والرجوع إلى جزء أداة تتبُّع النوم. من المفترض أن يتم تعديل شاشة الميزان تلقائيًا لعرض القيمة المعدَّلة للمستخدم. عليك إنشاء ViewModel وViewModelFactory، كما عليك تعديل SleepQualityFragment.

الخطوة 1: إنشاء ViewModel وViewModelFactory

  1. في حزمة sleepquality، أنشئ الملف SleepQualityViewModel.kt أو افتحه.
  2. أنشئ فئة SleepQualityViewModel تأخذ sleepNightKey وقاعدة بيانات كمعلَمات. كما فعلت مع SleepTrackerViewModel، عليك تمرير database من المصنع. يجب أيضًا تمرير sleepNightKey من التنقّل.
class SleepQualityViewModel(
       private val sleepNightKey: Long = 0L,
       val database: SleepDatabaseDao) : ViewModel() {
}
  1. داخل الفئة SleepQualityViewModel، حدِّد Job وuiScope، وألغِ onCleared().
    .
private val viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)

override fun onCleared() {
   super.onCleared()
   viewModelJob.cancel()
}
  1. للانتقال إلى SleepTrackerFragment باستخدام النمط نفسه المذكور أعلاه، عليك تعريف _navigateToSleepTracker. نفِّذ الترميزَين navigateToSleepTracker وdoneNavigating().
private val _navigateToSleepTracker = MutableLiveData<Boolean?>()

val navigateToSleepTracker: LiveData<Boolean?>
   get() = _navigateToSleepTracker

fun doneNavigating() {
   _navigateToSleepTracker.value = null
}
  1. أنشئ معالج نقرة واحدًا، onSetSleepQuality()، لجميع صور جودة النوم التي تريد استخدامها.

    استخدِم نمط الروتين الفرعي نفسه كما في الدرس العملي السابق:
  • ابدأ روتينًا فرعيًا في uiScope، ثم انتقِل إلى أداة توزيع عمليات الإدخال والإخراج.
  • يمكنك الحصول على tonight باستخدام sleepNightKey.
  • اضبط جودة النوم.
  • تعديل قاعدة البيانات
  • بدء التنقّل

لاحظ أنّ نموذج الرمز البرمجي أدناه ينفّذ كل العمل في معالج النقرات، بدلاً من استبعاد عملية قاعدة البيانات في السياق المختلف.

fun onSetSleepQuality(quality: Int) {
        uiScope.launch {
            // IO is a thread pool for running operations that access the disk, such as
            // our Room database.
            withContext(Dispatchers.IO) {
                val tonight = database.get(sleepNightKey) ?: return@withContext
                tonight.sleepQuality = quality
                database.update(tonight)
            }

            // Setting this state variable to true will alert the observer and trigger navigation.
            _navigateToSleepTracker.value = true
        }
    }
  1. في حزمة sleepquality، أنشئ SleepQualityViewModelFactory.kt أو افتحه وأضِف فئة SleepQualityViewModelFactory، كما هو موضّح أدناه. يستخدم هذا الصف إصدارًا من رمز النموذج نفسه الذي سبق أن رأيته. يُرجى فحص الرمز البرمجي قبل المتابعة.
class SleepQualityViewModelFactory(
       private val sleepNightKey: Long,
       private val dataSource: SleepDatabaseDao) : ViewModelProvider.Factory {
   @Suppress("unchecked_cast")
   override fun <T : ViewModel?> create(modelClass: Class<T>): T {
       if (modelClass.isAssignableFrom(SleepQualityViewModel::class.java)) {
           return SleepQualityViewModel(sleepNightKey, dataSource) as T
       }
       throw IllegalArgumentException("Unknown ViewModel class")
   }
}

الخطوة 2: تعديل SleepQualityFragment

  1. فتح "SleepQualityFragment.kt"
  2. في onCreateView()، بعد الحصول على application، عليك الحصول على arguments الذي تم تضمينه مع نظام الملاحة. تكون هذه الوسيطات في SleepQualityFragmentArgs. عليك استخراجها من الحزمة.
val arguments = SleepQualityFragmentArgs.fromBundle(arguments!!)
  1. بعد ذلك، احصل على dataSource.
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
  1. أنشئ مصنعًا، مع إدخال dataSource وsleepNightKey.
val viewModelFactory = SleepQualityViewModelFactory(arguments.sleepNightKey, dataSource)
  1. الحصول على مرجع ViewModel
val sleepQualityViewModel =
       ViewModelProviders.of(
               this, viewModelFactory).get(SleepQualityViewModel::class.java)
  1. أضِف ViewModel إلى عنصر الربط. (إذا ظهر لك خطأ في عنصر الربط، تجاهله في الوقت الحالي).
binding.sleepQualityViewModel = sleepQualityViewModel
  1. أضِف المراقب. عندما يُطلب منك ذلك، استورِد androidx.lifecycle.Observer.
sleepQualityViewModel.navigateToSleepTracker.observe(this, Observer {
   if (it == true) { // Observed state is true.
       this.findNavController().navigate(
               SleepQualityFragmentDirections.actionSleepQualityFragmentToSleepTrackerFragment())
       sleepQualityViewModel.doneNavigating()
   }
})

الخطوة 3: تعديل ملف التصميم وتشغيل التطبيق

  1. افتح ملف التنسيق fragment_sleep_quality.xml. في المربّع <data>، أضِف متغيّرًا لـ SleepQualityViewModel.
 <data>
       <variable
           name="sleepQualityViewModel"
           type="com.example.android.trackmysleepquality.sleepquality.SleepQualityViewModel" />
   </data>
  1. لكل صورة من صور جودة النوم الست، أضِف أداة معالجة نقرات مثل تلك الواردة أدناه. مطابقة تقييم الجودة مع الصورة
android:onClick="@{() -> sleepQualityViewModel.onSetSleepQuality(5)}"
  1. نظِّف مشروعك وأعِد إنشاءه. من المفترض أن يحلّ ذلك أي أخطاء في عنصر الربط. بخلاف ذلك، امحِ ذاكرة التخزين المؤقت (ملف > إبطال ذاكرات التخزين المؤقت / إعادة التشغيل) وأعِد إنشاء تطبيقك.

تهانينا! لقد أنشأت للتو تطبيق قاعدة بيانات Room كاملاً باستخدام إجراءات فرعية.

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

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

الخطوة 1: تعديل حالات الأزرار

الفكرة هي ضبط حالة الزر بحيث يكون زر البدء فقط مفعّلاً في البداية، ما يعني أنّه يمكن النقر عليه.

بعد أن ينقر المستخدم على بدء، يتم تفعيل الزر إيقاف وإيقاف الزر بدء. لا يتم تفعيل الزر محو إلا عندما تكون هناك بيانات في قاعدة البيانات.

  1. افتح ملف التنسيق fragment_sleep_tracker.xml.
  2. أضِف السمة android:enabled إلى كل زر. السمة android:enabled هي قيمة منطقية تشير إلى ما إذا كان الزر مفعّلاً أم لا. (يمكن النقر على الزر المفعَّل، ولكن لا يمكن النقر على الزر غير المفعَّل). امنح السمة قيمة متغيرة للحالة ستحدّدها بعد قليل.

start_button:

android:enabled="@{sleepTrackerViewModel.startButtonVisible}"

stop_button:

android:enabled="@{sleepTrackerViewModel.stopButtonVisible}"

clear_button:

android:enabled="@{sleepTrackerViewModel.clearButtonVisible}"
  1. افتح SleepTrackerViewModel وأنشئ ثلاثة متغيرات مقابلة. عيِّن لكل متغيّر عملية تحويل تختبره.
  • يجب أن يكون زر بدء مفعَّلاً عندما تكون قيمة tonight هي null.
  • يجب تفعيل الزر إيقاف عندما لا تكون قيمة tonight هي null.
  • يجب تفعيل الزر محو فقط إذا كان nights، وبالتالي قاعدة البيانات، يحتوي على ليالٍ من النوم.
val startButtonVisible = Transformations.map(tonight) {
   it == null
}
val stopButtonVisible = Transformations.map(tonight) {
   it != null
}
val clearButtonVisible = Transformations.map(nights) {
   it?.isNotEmpty()
}
  1. شغِّل تطبيقك وجرِّب الأزرار.

الخطوة 2: استخدام شريط إعلام منبثق لإعلام المستخدم

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

عرض شريط المعلومات هو مهمة خاصة بواجهة المستخدم، ويجب أن يتم ذلك في الجزء. يتم تحديد ما إذا كان سيتم عرض شريط المعلومات في ViewModel. لإعداد شريط معلومات سريع وعرضه عند محو البيانات، يمكنك استخدام الأسلوب نفسه المستخدَم لعرض شريط التنقّل.

  1. في SleepTrackerViewModel، أنشئ الحدث المغلف.
private var _showSnackbarEvent = MutableLiveData<Boolean>()

val showSnackBarEvent: LiveData<Boolean>
   get() = _showSnackbarEvent
  1. بعد ذلك، نفِّذ doneShowingSnackbar().
fun doneShowingSnackbar() {
   _showSnackbarEvent.value = false
}
  1. في SleepTrackerFragment، ضمن onCreateView()، أضِف مراقبًا باتّباع الخطوات التالية:
sleepTrackerViewModel.showSnackBarEvent.observe(this, Observer { })
  1. داخل كتلة المراقب، اعرض شريط المعلومات وأعِد ضبط الحدث على الفور.
   if (it == true) { // Observed state is true.
       Snackbar.make(
               activity!!.findViewById(android.R.id.content),
               getString(R.string.cleared_message),
               Snackbar.LENGTH_SHORT // How long to display the message.
       ).show()
       sleepTrackerViewModel.doneShowingSnackbar()
   }
  1. في SleepTrackerViewModel، شغِّل الحدث في الطريقة onClear(). لإجراء ذلك، اضبط قيمة الحدث على true داخل الحظر launch:
_showSnackbarEvent.value = true
  1. أنشئ تطبيقك وشغِّله.

مشروع "استوديو Android": TrackMySleepQualityFinal

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

  • أنشئ ViewModel وViewModelFactory وأعِدّ مصدر بيانات.
  • بدء التنقّل لفصل الاهتمامات، ضَع معالج النقرات في نموذج العرض والتنقّل في الجزء.
  • استخدِم التغليف مع LiveData لتتبُّع تغييرات الحالة والردّ عليها.
  • استخدام عمليات التحويل مع LiveData
  • إنشاء قاعدة بيانات ذات مثيل واحد
  • إعداد إجراءات روتينية لعمليات قاعدة البيانات

بدء التنقّل

يمكنك تحديد مسارات التنقّل المحتملة بين الأجزاء في ملف تنقّل. هناك بعض الطرق المختلفة لتفعيل التنقّل من جزء إلى آخر. ومن بينها:

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

ضبط السمة android:enabled

  • يتم تحديد السمة android:enabled في TextView ويتم توريثها من خلال جميع الفئات الفرعية، بما في ذلك Button.
  • تحدّد السمة android:enabled ما إذا كان View مفعَّلاً أم لا. يختلف معنى "مفعَّل" حسب الفئة الفرعية. على سبيل المثال، يمنع العنصر EditText غير المفعَّل المستخدم من تعديل النص المضمّن، ويمنع العنصر Button غير المفعَّل المستخدم من النقر على الزر.
  • السمة enabled ليست هي نفسها السمة visibility.
  • يمكنك استخدام خرائط التحويل لضبط قيمة السمة enabled للأزرار استنادًا إلى حالة عنصر أو متغيّر آخر.

في ما يلي نقاط أخرى يتناولها هذا الدرس التطبيقي حول الترميز:

  • لتفعيل الإشعارات للمستخدم، يمكنك استخدام الأسلوب نفسه الذي تستخدمه لتفعيل التنقّل.
  • يمكنك استخدام Snackbar لإرسال إشعار إلى المستخدم.

دورة Udacity التدريبية:

مستندات مطوّري تطبيقات Android:

يسرد هذا القسم مهامًا منزلية محتملة للطلاب الذين يعملون على هذا الدرس التطبيقي العملي كجزء من دورة تدريبية يقودها مدرّب. على المعلّم تنفيذ ما يلي:

  • حدِّد واجبًا منزليًا إذا لزم الأمر.
  • توضيح كيفية إرسال الواجبات المنزلية للطلاب
  • وضع درجات للواجبات المنزلية

يمكن للمدرّبين استخدام هذه الاقتراحات بالقدر الذي يريدونه، ويجب ألا يترددوا في تكليف الطلاب بأي واجبات منزلية أخرى يرونها مناسبة.

إذا كنت تعمل على هذا الدرس العملي بنفسك، يمكنك استخدام مهام الواجب المنزلي هذه لاختبار معلوماتك.

الإجابة عن هذه الأسئلة

السؤال 1

إحدى طرق السماح لتطبيقك بتفعيل التنقّل من جزء إلى آخر هي استخدام قيمة LiveData للإشارة إلى ما إذا كان سيتم تفعيل التنقّل أم لا.

ما هي خطوات استخدام قيمة LiveData، والتي تُسمى gotoBlueFragment، لتفعيل التنقّل من الجزء الأحمر إلى الجزء الأزرق؟ اختر كلّ الإجابات المنطبقة.

  • في ViewModel، حدِّد قيمة LiveData gotoBlueFragment.
  • في RedFragment، لاحظ قيمة gotoBlueFragment. نفِّذ الرمز observe{} للانتقال إلى BlueFragment عند الاقتضاء، ثم أعِد ضبط قيمة gotoBlueFragment للإشارة إلى اكتمال عملية التنقّل.
  • تأكَّد من أنّ الرمز البرمجي يضبط المتغيّر gotoBlueFragment على القيمة التي تؤدي إلى التنقّل كلّما احتاج التطبيق إلى الانتقال من RedFragment إلى BlueFragment.
  • تأكَّد من أنّ الرمز البرمجي يحدّد معالج onClick للعنصر View الذي ينقر عليه المستخدم للانتقال إلى BlueFragment، حيث يراقب معالج onClick القيمة goToBlueFragment.

السؤال 2

يمكنك تغيير ما إذا كان Button مفعَّلاً (يمكن النقر عليه) أو لا باستخدام LiveData. كيف يمكنك التأكّد من أنّ تطبيقك يغيّر الزر UpdateNumber على النحو التالي:

  • يكون الزر مفعَّلاً إذا كانت قيمة myNumber أكبر من 5.
  • لا يتم تفعيل الزر إذا كان myNumber يساوي 5 أو أقل.

لنفترض أنّ التنسيق الذي يحتوي على الزر UpdateNumber يتضمّن المتغيّر <data> الخاص بـ NumbersViewModel كما هو موضّح هنا:

<data>
   <variable
       name="NumbersViewModel"
       type="com.example.android.numbersapp.NumbersViewModel" />
</data>

لنفترض أنّ معرّف الزرّ في ملف التصميم هو ما يلي:

android:id="@+id/update_number_button"

ما هي الإجراءات الأخرى التي عليك اتّخاذها؟ يُرجى اختيار جميع الإجابات المناسبة.

  • في الفئة NumbersViewModel، حدِّد المتغيّر LiveData، myNumber، الذي يمثّل الرقم. حدِّد أيضًا متغيّرًا يتم ضبط قيمته من خلال استدعاء Transform.map() على المتغيّر myNumber، ما يؤدي إلى عرض قيمة منطقية تشير إلى ما إذا كان الرقم أكبر من 5 أم لا.

    على وجه التحديد، في ViewModel، أضِف الرمز التالي:
val myNumber: LiveData<Int>

val enableUpdateNumberButton = Transformations.map(myNumber) {
   myNumber > 5
}
  • في تنسيق XML، اضبط السمة android:enabled للعنصر update_number_button button على NumberViewModel.enableUpdateNumbersButton.
android:enabled="@{NumbersViewModel.enableUpdateNumberButton}"
  • في Fragment الذي يستخدم الفئة NumbersViewModel، أضِف مراقبًا إلى السمة enabled للزر.

    على وجه التحديد، في Fragment، أضِف الرمز التالي:
// Observer for the enabled attribute
viewModel.enabled.observe(this, Observer<Boolean> { isEnabled ->
   myNumber > 5
})
  • في ملف التصميم، اضبط السمة android:enabled للعنصر update_number_button button على "Observable".

انتقِل إلى الدرس التالي: ‫7.1 أساسيات RecyclerView

للحصول على روابط تؤدي إلى دروس تطبيقية أخرى في هذه الدورة التدريبية، اطّلِع على الصفحة المقصودة الخاصة بالدروس التطبيقية حول أساسيات Android Kotlin.