Android Kotlin Fundamentals 04.1: مراحل النشاط والتسجيل

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

مقدمة

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

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

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

ما يجب معرفته

  • تعريف النشاط وكيفية إنشاء نشاط في تطبيقك
  • وظيفة onCreate() للنشاط، ونوع العمليات التي يتم تنفيذها بهذه الطريقة.
  • كيفية إنشاء تنسيقات XML لنشاطك وكيفية تعديل تخطيط في وقت التشغيل.

ما ستتعرّف عليه

  • كيفية طباعة معلومات التسجيل إلى Logcat (تُسمّى أحيانًا وحدة تحكم Android أو شاشة Android)
  • أساسيات مراحل نشاط Activity وFragment، واستدعاءات الاستدعاء التي تم استدعاؤها عند انتقال النشاط بين الولايات.
  • كيفية إلغاء أساليب استدعاء دورة الحياة لتنفيذ العمليات في أوقات مختلفة في مراحل نشاط النشاط.
  • كيفية استخدام مكتبة Timber لتسجيل الدخول إلى تطبيقك.

المهام التي ستنفذها

  • عدِّل تطبيق بدء التشغيل باسم DessertClicker لإضافة معلومات التسجيل التي يتم عرضها في Logcat.
  • إلغاء طرق معاودة الاتصال بدورة الحياة وتسجيل التغييرات في حالة النشاط
  • شغِّل التطبيق ولاحظ معلومات تسجيل الدخول التي تظهر عند بدء النشاط أو توقفه أو استئنافه.
  • عدِّل التطبيق لاستخدام مكتبة Timber.
  • إضافة تسجيل إلى تطبيق AndroidTrivia ومراقبة التغييرات في حالات الأجزاء.

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

يحتوي هذا التطبيق على العديد من الأخطاء التي تتعلق بمراحل نشاط Android: على سبيل المثال، في حالات معينة، يعيد التطبيق ضبط قيم الحلويات على 0، ويستمر التطبيق في استخدام موارد النظام حتى عندما يكون التطبيق في الخلفية. وسيساعدك فهم مراحل نشاط نظام التشغيل Android في فهم سبب حدوث هذه المشاكل وكيفية حلها.

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

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

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

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

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

الخطوة 1: فحص طريقة onCreate() وإضافة التسجيل

لمعرفة ما يحدث في دورة حياة Android، من المفيد معرفة وقت استدعاء الطرق المختلفة لمراحل الحياة. وسيساعدك ذلك على البحث عن الأخطاء في DessertClicker.

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

  1. نزِّل تطبيق DessertClicker Starter وافتحه في "استوديو Android".
  2. اجمع التطبيق وشغِّله، ثم انقر عدة مرات على صورة الحلوى. لاحظ كيف تتغير قيمة الحلويات المباعة وإجمالي مبلغ الدولار.
  3. افتح MainActivity.kt وافحص طريقة onCreate() لهذا النشاط.
override fun onCreate(savedInstanceState: Bundle?) {
...
}

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

يتم استدعاء طريقة دورة حياة onCreate() مرة واحدة فقط، بعد إعداد النشاط (عندما يتم إنشاء عنصر Activity الجديد في الذاكرة). بعد تنفيذ onCreate()، يُعتبر النشاط منشأًا.

  1. في الطريقة onCreate()، بعد السطر التالي إلى super.onCreate()، أضِف السطر التالي. استورِد الصف Log إذا لزم الأمر. (اضغط على Alt+Enter أو Option+Enter على جهاز Mac، واختَر استيراد).
Log.i("MainActivity", "onCreate Called")

يُكتب الطلاب في فئة Log الرسائل إلى Logcat. هناك ثلاثة أجزاء في هذا الأمر:

  • درجة خطورة رسالة السجل، بمعنى أهمية الرسالة. في هذه الحالة، تكتب طريقة Log.i() رسالة إعلامية. وتشمل الطرق الأخرى في الصف Log السمة Log.e() للأخطاء أو Log.w() للتحذيرات.
  • سجلّ العلامة، وفي هذه الحالة "MainActivity". والعلامة عبارة عن سلسلة تتيح لك العثور على رسائل السجل في Logcat بسهولة أكبر. وتكون العلامة عادةً اسم الصف.
  • سجلّ الرسالة، هو سلسلة قصيرة، وهي في هذه الحالة "onCreate called".
  1. اجمَع تطبيق DessertClicker وفعِّله، ولن تلاحظ أي اختلافات في السلوك في التطبيق عند النقر على الحلوى. في "استوديو Android"، انقر على علامة التبويب Logcat في أسفل الشاشة.



    Logcat هي وحدة التحكّم لتسجيل الرسائل. تظهر الرسائل الواردة من Android حول تطبيقك هنا، بما في ذلك الرسائل التي ترسلها صراحةً إلى السجلّ باستخدام طريقة Log.i() أو طرق Log الأخرى.
  2. في جزء Logcat (الكتابة في Logcat)، اكتب I/MainActivity في حقل البحث.


    يمكن أن يحتوي Logcat على رسائل كثيرة، معظمها غير مفيد لك. يمكنك فلترة إدخالات Logcat بطرق متعددة، ولكن عملية البحث هي الأسهل. بما أنّك استخدمت MainActivity كعلامة السجلّ في رمزك، يمكنك استخدام هذه العلامة لفلترة السجلّ. تعني إضافة I/ في البداية أن هذه رسالة إعلامية تم إنشاؤها بواسطة Log.i().

    تتضمن رسالة السجل التاريخ والوقت، واسم الحزمة (com.example.android.dessertclicker)، وعلامة السجل (مع I/ في البداية)، والرسالة الفعلية. بما أنّ هذه الرسالة تظهر في السجلّ، أنت تعرف أنّه تمّ تنفيذ onCreate().

الخطوة 2: تنفيذ طريقة onStart()

يتم استدعاء طريقة دورة حياة onStart() بعد onCreate() مباشرةً. بعد تشغيل onStart()، يكون نشاطك مرئيًا على الشاشة. بخلاف onCreate()، الذي يُطلب مرة واحدة فقط لإعداد نشاطك، يمكن استدعاء onStart() عدة مرات في دورة حياة نشاطك.

تجدُر الإشارة إلى أنه يتم إقران onStart() بطريقة دورة حياة onStop() المقابلة. إذا شغَّل المستخدم تطبيقك ثم عاد إلى الشاشة الرئيسية للجهاز، يتم إيقاف النشاط ولن يظهر على الشاشة.

  1. في "استوديو Android"، مع فتح MainActivity.kt، اختَر الرمز &gt؛ سيتم إلغاء الطرق أو اضغط على Control+o. يظهر مربّع حوار يتضمن قائمة كبيرة من جميع الطرق التي يمكنك تجاوزها في هذا الصف.
  2. ابدأ في إدخال onStart للبحث عن الطريقة الصحيحة. للانتقال إلى العنصر المطابق التالي، استخدِم السهم المتجه للأسفل. اختَر onStart() من القائمة، وانقر على OK (حسنًا) لإدراج رمز التجاوز المعياري. يبدو الرمز كما يلي:
override fun onStart() {
   super.onStart()
}
  1. ضمن طريقة onStart()، أضِف رسالة سجلّ:
override fun onStart() {
   super.onStart()

   Log.i("MainActivity", "onStart Called")
}
  1. اجمَع تطبيق DessertClicker وشغِّله، ثم افتح لوحة Logcat. اكتب I/MainActivity في حقل البحث لفلترة السجل. تجدر الإشارة إلى أنّه تم طلب كلٍ من طريقتَي onCreate() وonStart() واحدة تلو الأخرى، وأنّ نشاطك كان مرئيًا على الشاشة.
  2. اضغط على زر الشاشة الرئيسية على الجهاز، ثم استخدم شاشة المكالمات الأخيرة للعودة إلى النشاط. يُرجى ملاحظة أنّ النشاط يستأنف نشاطه من حيث توقّف، باستخدام كل القيم نفسها، وأنّه يتم تسجيل onStart() للمرة الثانية في Logcat. يُرجى أيضًا ملاحظة أنه لا يتم استدعاء طريقة onCreate() عادةً مرة أخرى.

في هذه المهمة، يمكنك تعديل تطبيقك لاستخدام مكتبة تسجيل شائعة تُسمى Timber. هناك العديد من المزايا لـ Timber مقارنةً بصف Log المدمج في Android. وعلى وجه الخصوص، تعمل مكتبة Timber على:

  • إنشاء علامة السجل لك استنادًا إلى اسم الفئة.
  • يساعدك على تجنب عرض السجلات في إصدار إصدار من تطبيق Android.
  • تسمح هذه السياسة بالدمج مع مكتبات تقارير الأعطال.

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

الخطوة 1: إضافة الأخشاب إلى Gradle

  1. انتقِل إلى هذا الرابط الذي يؤدي إلى مشروع الأخشاب على GitHub، وانسخ سطر الرمز ضمن العنوان تنزيل الذي يبدأ بالكلمة implementation. سيبدو سطر الرمز مشابهًا لما يلي، على الرغم من أن رقم الإصدار قد يكون مختلفًا.
implementation 'com.jakewharton.timber:timber:4.7.1'
  1. في "استوديو Android"، ضمن "المشروع: عرض Android"، وسِّع Gradle Scripts، وافتح ملف build.gradle (الوحدة: التطبيق).
  2. داخل قسم التبعيات، الصق سطر الرمز الذي نسخته.
dependencies {
   ...
   implementation 'com.jakewharton.timber:timber:4.7.1'
}
  1. انقر على الرابط المزامنة الآن في أعلى يسار الصفحة في "استوديو Android" لإعادة إنشاء Gradle. يجب تنفيذ الإصدار بدون أخطاء.

الخطوة 2: إنشاء فئة تطبيق وإعداد الأخشاب

ستنشئ في هذه الخطوة صفًا واحدًا (Application). Application هي فئة أساسية تحتوي على حالة التطبيق العامة لتطبيقك بالكامل. كما أنها الكائن الرئيسي الذي يستخدمه نظام التشغيل للتفاعل مع تطبيقك. هناك فئة Application تلقائية يستخدمها Android إذا لم تحدد فئة، لذلك يوجد دائمًا كائن Application تم إنشاؤه لتطبيقك، بدون الحاجة إلى اتخاذ أي إجراء خاص لإنشائه.

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

بعد إنشاء صف Application، ستحتاج إلى تحديد الفئة في بيان Android.

  1. في حزمة dessertclicker، أنشِئ فئة Kotlin جديدة باسم ClickerApplication. ولإجراء ذلك، وسِّع app > java وانقر بزر الماوس الأيمن على com.example.android.حلوىclicker. اختَر جديد > Kotlin File/Class.
  2. أدخِل اسمًا للصف ClickerApplication واضبط النوع على الصف. انقر على حسنًا.

وينشئ"استوديو Android"صفًا جديدًا على ClickerApplication ويفتحه في أداة تعديل الرموز. يبدو الرمز كما يلي:

package com.example.android.dessertclicker

class ClickerApplication {
}
  1. غيِّر تعريف الفئة إلى فئة فرعية من Application واحرص على استيراد الفئة Application إذا لزم الأمر.
class ClickerApplication : Application() {
  1. ولإلغاء طريقة onCreate()، اختَر الرمز &gt؛ أو إلغاء الطرق أو اضغط على Control+o.
class ClickerApplication : Application() {
   override fun onCreate() {
       super.onCreate()
   }
}
  1. داخل طريقة onCreate() هذه، عليك إعداد مكتبة Timber:
override fun onCreate() {
    super.onCreate()

    Timber.plant(Timber.DebugTree())
}

يؤدي سطر الرمز هذا إلى إعداد مكتبة Timber لتطبيقك بحيث يمكنك استخدام المكتبة في أنشطتك.

  1. افتح AndroidManifest.xml.
  2. في أعلى العنصر <application>، أضِف سمة جديدة للصف ClickerApplication، حتى يعرف نظام التشغيل Android استخدام الصف Application بدلاً من السمة التلقائية.
<application
   android:name=".ClickerApplication"
...

الخطوة 3: إضافة كشوفات السجلّات للأخشاب

في هذه الخطوة، يمكنك تغيير مكالمات Log.i() لاستخدام Timber، ثم تنفيذ التسجيل لكل طرق مراحل النشاط الأخرى.

  1. افتح MainActivity وانتقِل إلى onCreate(). استبدِل Log.i() بـ Timber.i() وأزِل علامة السجلّ.
Timber.i("onCreate called")

كما هو الحال في الصف Log، يستخدم Timber أيضًا طريقة i() للرسائل الإعلامية. تجدر الإشارة إلى أنك لن تحتاج إلى إضافة علامة سجل في Timber، لأن Timber يستخدم تلقائيًا اسم الفئة كعلامة سجل.

  1. بالمثل، غيِّر المكالمة Log في onStart():
override fun onStart() {
   super.onStart()

   Timber.i("onStart Called")
}
  1. اجمَع تطبيق DessertClicker وشغِّله، واطّلِع على Logcat. يُرجى العلم بأنّه لا يزال بإمكانك عرض رسائل السجلّ نفسها لـ onCreate() وonStart()، وأنّها Timber فقط تنشئ هذه الرسائل، وليس الصف Log.
  2. ويمكنك إلغاء بقية طرق مراحل النشاط في MainActivity، وإضافة عبارات سجلات Timber لكل طريقة. وإليك الرمز:
override fun onResume() {
   super.onResume()
   Timber.i("onResume Called")
}

override fun onPause() {
   super.onPause()
   Timber.i("onPause Called")
}

override fun onStop() {
   super.onStop()
   Timber.i("onStop Called")
}

override fun onDestroy() {
   super.onDestroy()
   Timber.i("onDestroy Called")
}

override fun onRestart() {
   super.onRestart()
   Timber.i("onRestart Called")
}
  1. اجمَع وجرِّب DessertClicker مرة أخرى وافحص Logcat. لاحظ في هذا الوقت أنه بالإضافة إلى onCreate() وonStart()، هناك رسالة سجل لاستدعاء دورة حياة onResume().

عندما يبدأ أحد الأنشطة من البداية، سترى جميع عمليات الاسترداد الثلاث التالية لدورة الحياة بالترتيب:

  • onCreate() لإنشاء التطبيق
  • onStart() لتشغيله وجعله مرئيًا على الشاشة.
  • onResume() لإعطاء تركيز النشاط وتجهيزه للتفاعل من جانب المستخدم.

على الرغم من الاسم، يتم استدعاء الطريقة onResume() عند بدء التشغيل، حتى إذا لم يكن هناك شيء لاستئنافه.

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

حالة الاستخدام 1: فتح النشاط وإغلاقه

تبدأ بحالة الاستخدام الأساسية، وهي بدء تشغيل تطبيقك لأول مرة، ثم إغلاق التطبيق تمامًا.

  1. اجمع تطبيق DessertClicker وشغِّله، إذا لم يكن قيد التشغيل. كما رأيت، يتم الاتصال باستدعاءات onCreate() وonStart() وonResume() عند بدء النشاط لأول مرة.
  2. انقر على الكب كيك بضع مرات.
  3. انقر على زر الرجوع على الجهاز. لاحظ في Logcat أنه يتم استدعاء onPause() وonStop() وonDestroy() بهذا الترتيب.

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

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


    تمّ محو النشاط في الخطوة السابقة، لذا عند عودتك إلى التطبيق، يبدأ نظام Android نشاطًا جديدًا ثم يتصل بطرق onCreate() وonStart() وonResume(). لاحظ أنه لم يتم الاحتفاظ بأي من إحصاءات DessertClicker من النشاط السابق.

    وتكمن النقطة الرئيسية هنا في أنّه يتم استدعاء onCreate() وonDestroy() مرة واحدة فقط خلال فترة أي نشاط واحد: onCreate() لإعداد التطبيق للمرة الأولى، وonDestroy() لتنظيف الموارد التي يستخدمها تطبيقك.

    تُعدّ طريقة onCreate() خطوة مهمة، وهي المكان الذي يتم فيه إعداد الإعداد للمرة الأولى، حيث يتم إعداد التنسيق للمرة الأولى من خلال تضخيمه والمكان الذي يتم فيه إعداد المتغيرات.

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

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

لا يتم إغلاق نشاطك تمامًا في كل مرة ينتقل فيها المستخدم بعيدًا عن هذا النشاط:

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

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

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

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

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

  1. أثناء تشغيل تطبيق DessertClicker، انقر على الكب كيك بضع مرات.
  2. اضغط على زر الشاشة الرئيسية على جهازك ولاحظ Logcat في Android Studio. تؤدي العودة إلى الشاشة الرئيسية إلى وضع تطبيقك في الخلفية بدلاً من إغلاق التطبيق. لاحِظ أنه يتم استدعاء النهجَين onPause() وonStop()، ولكن لا يتم استدعاء الدالة onDestroy().


    عند استدعاء الدالة onPause()، لن يبقى التركيز في التطبيق بعد الآن. وبعد onStop()، لن يظهر التطبيق على الشاشة. على الرغم من إيقاف النشاط، لا يزال الكائن Activity في الذاكرة، في الخلفية. لم يتم إتلاف النشاط. قد يعود المستخدم إلى التطبيق حتى يحافظ Android على موارد نشاطك في مكان قريب.
  3. استخدِم شاشة التطبيقات الأخيرة للعودة إلى التطبيق. لاحظ في Logcat أن النشاط ستتم إعادة تشغيله باستخدام onRestart() وonStart()، ثم تم استئنافه بواسطة onResume().


    عند عودة النشاط إلى المقدّمة، لا يتم استدعاء طريقة onCreate() مرة أخرى. لم يتم إتلاف كائن النشاط، لذلك لا ينبغي إنشاؤه مرة أخرى. بدلاً من onCreate()، يتم استدعاء الطريقة onRestart(). لاحظ أنّه في هذه المرة التي يعود فيها النشاط إلى المقدمة، يتم الاحتفاظ برقم الحلويات المُباعة.
  4. ابدأ تشغيل تطبيق واحد على الأقل بخلاف DessertClicker حتى يحتوي الجهاز على بعض التطبيقات في الشاشة الأخيرة.
  5. انتقِل إلى الشاشة الأخيرة وافتح نشاطًا آخر. وبعد ذلك، يمكنك الرجوع إلى التطبيقات المستخدمة مؤخرًا وجلب الحلويات إلى المقدمة في المقدمة.

    لاحظ أنك ترى عمليات الاستدعاء نفسها في Logcat هنا كما لو ضغطت على زر الشاشة الرئيسية. يتم استدعاء التطبيق onPause() وonStop() عندما يستخدم التطبيق الخلفية، ثم يردّ onRestart() وonStart() وonResume() عند ظهوره مجددًا.

    النقطة المهمة هنا هي أنه يتم استدعاء onStart() وonStop() عدة مرات أثناء انتقال المستخدم من النشاط وإليه. يجب إلغاء هذه الطرق لإيقاف التطبيق عند نقله إلى الخلفية أو تشغيله مرة أخرى عند ظهوره في المقدّمة.

    ماذا عن onRestart()؟ طريقة onRestart() تشبه إلى حد كبير onCreate(). يتم استدعاء الدالة onCreate() أو onRestart() قبل أن يصبح النشاط مرئيًا. يتم استدعاء الطريقة onCreate() فقط في المرة الأولى، ويتم استدعاء onRestart() بعد ذلك. طريقة onRestart() هي مكان لإضافة الرمز الذي تريد الاتصال به فقط إذا لم يتم بدء نشاطك لأول مرة.

حالة الاستخدام 3: إخفاء النشاط جزئيًا

لقد تعلمت أنه عند بدء تشغيل تطبيق واستدعاء onStart()، يصبح التطبيق مرئيًا على الشاشة. عند استئناف التطبيق واستدعاء onResume()، يكتسب التطبيق تركيز المستخدم. يُسمى الجزء الذي يظهر في التطبيق بشكل كامل على الشاشة والذي يظهر فيه تركيز المستخدم دورة حياة التفاعل.

عند انتقال التطبيق إلى الخلفية، يفقد التركيز بعد onPause()، ولا يكون التطبيق مرئيًا بعد onStop().

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

  1. أثناء تشغيل تطبيق DessertClicker، انقر على الزر مشاركة في أعلى يسار الشاشة.




    يظهر نشاط المشاركة في النصف السفلي من الشاشة، ولكن يظل النشاط مرئيًا في النصف العلوي.
  2. افحص Logcat ولاحِظ أنه تم استدعاء onPause() فقط.


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

    ما سبب أهمية هذا الاختلاف؟ لنأخذ التطبيق الفيزيائي الذي قد تريد إيقاف المحاكاة عندما يكون التطبيق في الخلفية مع الاستمرار في تشغيله عندما يكون التطبيق غير معروف جزئيًا. في هذه الحالة، يمكنك إيقاف المحاكاة في onStop(). إذا أردت أن تتوقّف المحاكاة عند إخفاء النشاط جزئيًا، يمكنك وضع الرمز لإيقاف المحاكاة في onPause().

    أيًا كان الرمز الذي يتم تشغيله في onPause() يمنع عرض عناصر أخرى، لذا حافظ على الرمز فارغًا في onPause(). على سبيل المثال، إذا ظهرت مكالمة هاتفية، قد يؤدي الرمز في onPause() إلى تأخير إشعار المكالمة الواردة.
  3. انقر خارج مربّع حوار المشاركة للعودة إلى التطبيق، ولاحظ أنّه تم استدعاء تطبيق onResume().

    كل من onResume() وonPause() مرتبطان بالتركيز. ويتم استدعاء الطريقة onResume() عندما يكون للنشاط تركيز التركيز، ويتم استدعاء onPause() عندما يفقد النشاط التركيز.

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

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

كل شاشة في تطبيق AndroidTrivia هي Fragment.

ولتبسيط الأمور، يمكنك استخدام واجهة برمجة التطبيقات لتسجيل Android في هذه المهمة، بدلاً من مكتبة Timber.

  1. افتح تطبيق AndroidTrivia من آخر درس تطبيقي حول الترميز، أو نزِّل رمز الحل AndroidTrivia من GitHub.
  2. افتح ملف TitleFragment.kt. وتجدر الإشارة إلى أنّ "استوديو Android" قد يعرض أخطاءً ملزِمة وأخطاء لم يتمّ حلّها إلى أن تُعيد إنشاء التطبيق.
  3. انتقِل للأسفل إلى طريقة onCreateView(). يُرجى ملاحظة أنّ هنا الجزء الذي يتم فيه تضخيم تنسيق الجزء وربط البيانات.
  4. أضِف عبارة تسجيل إلى الطريقة onCreateView()، بين السطرين في setHasOptionsMenu() والمكالمة النهائية للعرض:
setHasOptionsMenu(true)

Log.i("TitleFragment", "onCreateView called")

return binding.root
  1. أسفل طريقة onCreateView()، أضِف عبارات التسجيل لكل طريقة من طرق مراحل النشاط المتبقية. إليك الرمز:
override fun onAttach(context: Context?) {
   super.onAttach(context)
   Log.i("TitleFragment", "onAttach called")
}
override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   Log.i("TitleFragment", "onCreate called")
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
   super.onActivityCreated(savedInstanceState)
   Log.i("TitleFragment", "onActivityCreated called")
}
override fun onStart() {
   super.onStart()
   Log.i("TitleFragment", "onStart called")
}
override fun onResume() {
   super.onResume()
   Log.i("TitleFragment", "onResume called")
}
override fun onPause() {
   super.onPause()
   Log.i("TitleFragment", "onPause called")
}
override fun onStop() {
   super.onStop()
   Log.i("TitleFragment", "onStop called")
}
override fun onDestroyView() {
   super.onDestroyView()
   Log.i("TitleFragment", "onDestroyView called")
}
override fun onDetach() {
   super.onDetach()
   Log.i("TitleFragment", "onDetach called")
}
  1. اجمَع التطبيق وشغِّله، وافتح Logcat.
  2. اكتب I/TitleFragment في حقل البحث لفلترة السجل. عند بدء تشغيل التطبيق، سيظهر Logcat على النحو التالي: لقطة الشاشة التالية:

يمكنك الاطّلاع هنا على مراحل نشاط بدء تشغيل الجزء، بما في ذلك عمليات الاستدعاء التالية:

  • onAttach(): يتم الاتصال عندما يكون الجزء مرتبطًا بنشاط مالكه.
  • onCreate(): على غرار onCreate() للنشاط، يُطلب من onCreate() للجزء إنشاء الجزء الأولي (بخلاف التنسيق).
  • onCreateView(): تم طلب تضخيم تنسيق الجزء.
  • onActivityCreated(): يتم الاتصال عند اكتمال onCreate() لنشاط المالك. لن يتمكن الجزء الخاص بك من الوصول إلى النشاط حتى يتم استدعاء هذه الطريقة.
  • onStart(): يتم طلب ذلك عندما يصبح الجزء مرئيًا. وبشكل موازٍ للنشاط onStart().
  • onResume(): يتم استدعاءه عندما يكتسب الجزء تركيز المستخدم، بالتوازي مع النشاط onResume().
  1. انقر على الزر تشغيل للانتقال إلى لعبة المعلومات العامة وملاحظة Logcat الآن.

ويؤدي فتح الجزء التالي إلى إغلاق جزء العنوان، وتسمية طرق مراحل النشاط هذه:

  • onPause(): يتم الاستدعاء عندما يفقد الجزء تركيز المستخدم، بالتوازي مع النشاط onPause().
  • onStop(): يتم طلب ذلك عندما لا يكون الجزء مرئيًا على الشاشة، بالتوازي مع النشاط onStop().
  • onDestroyView(): يتم استدعاء هذا الملف عندما لا تكون هناك حاجة إلى طريقة عرض"الجزء"لتنظيف الموارد المرتبطة بطريقة العرض هذه.
  1. في التطبيق، انقر على الزر للأعلى (السهم في أعلى يمين الشاشة) للعودة إلى جزء العنوان.


    من المحتمل ألا يتم استدعاء onAttach() وonCreate() لبدء الجزء. لا يزال الكائن المقطوع موجودًا وما زال مرتبطًا بنشاط المالك، لذلك تبدأ دورة الحياة مرة أخرى باستخدام onCreateView().
  2. اضغط على زر الشاشة الرئيسية للجهاز. لاحظ في Logcat أنه يتم استدعاء onPause() وonStop() فقط. هذا هو الإجراء نفسه الذي يتم تنفيذه في النشاط: يؤدي الرجوع إلى الصفحة الرئيسية إلى وضع النشاط والجزء في الخلفية.
  3. يمكنك استخدام شاشة الأخيرة للعودة إلى التطبيق. تمامًا كما حدث للنشاط، يتم طلب طريقتَي onStart() وonResume() لإعادة الجزء إلى المقدمة.

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

مراحل النشاط

  • دورة حياة النشاط هي مجموعة من الحالات التي يتم ترحيل نشاط من خلالها. تبدأ دورة حياة النشاط عند إنشاء النشاط لأول مرة وتنتهي عند إتلاف النشاط.
  • عندما يتنقل المستخدم بين الأنشطة وداخل التطبيق وخارجه، ينتقل كل نشاط بين الحالات في مراحل نشاط النشاط.
  • تتضمّن كل حالة في دورة حياة النشاط طريقة رد اتصال مطابقة يمكنك إلغاءها في صف Activity. هناك سبعة طرق لمراحل الحياة:
    onCreate()
    onStart()
    onPause()
    onRestart()
    onResume()
    onStop()
    onDestroy()
  • لإضافة سلوك يحدث عند انتقال نشاطك إلى حالة دورة حياة، يمكنك إلغاء طريقة استدعاء الحالة.
  • لإضافة طرق إلغاء الهيكل العظمي إلى صفوفك في Android Studio، اختَر Code > Override Methods أو اضغط على Control+o.

التسجيل باستخدام السجلّ

  • تتيح لك واجهة برمجة تطبيقات تسجيل Android، وبالأخص الفئة Log، كتابة رسائل قصيرة يتم عرضها في Logcat داخل Android Studio.
  • استخدِم Log.i() لكتابة رسالة إعلامية. تستخدِم هذه الطريقة وسيطتَين: علامة السجلّ، وعادةً ما تكون اسم الصف ورسالة السجلّ، سلسلة قصيرة.
  • استخدِم الجزء Logcat (لوحة الدليل) في "استوديو Android" لعرض سجلّات النظام، بما في ذلك الرسائل التي تكتبها.

التسجيل باستخدام الأخشاب

Timber هي مكتبة تسجيل تتضمن العديد من المزايا على واجهة برمجة تطبيقات تسجيل Android. وعلى وجه الخصوص، تعمل مكتبة Timber على:

  • إنشاء علامة السجل لك استنادًا إلى اسم الفئة.
  • يساعد على تجنب عرض السجلات في إصدار إصدار من تطبيق Android.
  • تسمح هذه السياسة بالدمج مع مكتبات تقارير الأعطال.

لاستخدام Timber، أضِف اعتماديتها إلى ملف Gradle ووسِّع فئة Application لإعدادها:

  • Application هي فئة أساسية تحتوي على حالة التطبيق العامة لتطبيقك بالكامل. وهناك فئة Application تلقائية يستخدمها Android إذا لم تحدّد أي فئة. ويمكنك إنشاء فئتك الفرعية على Application لإعداد المكتبات على مستوى التطبيق مثل Timber.
  • أضِف فئة Application المخصّصة إلى تطبيقك من خلال إضافة السمة android:name إلى العنصر <application> في بيان Android. لا تنسَ فعل ذلك.
  • استخدِم Timber.i() لكتابة رسائل السجلّ باستخدام Timber. تتطلب هذه الطريقة وسيطة واحدة فقط: الرسالة المراد كتابتها. تتم إضافة علامة السجل (اسم الفئة) لك تلقائيًا.

دورة Udacity:

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

غير ذلك:

يسرد هذا القسم المهام الدراسية المحتملة للطلاب الذين يعملون من خلال هذا الدرس التطبيقي حول الترميز في إطار دورة تدريبية يُديرها معلِّم. يجب أن ينفِّذ المعلّم ما يلي:

  • يمكنك تخصيص واجب منزلي إذا لزم الأمر.
  • التواصل مع الطلاب بشأن كيفية إرسال الواجبات المنزلية
  • وضع درجات للواجبات المنزلية.

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

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

تغيير تطبيق

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

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

السؤال 1

أي مما يلي ليس من مراحل نشاط النشاط؟

  • مشغَّل
  • في الانتظار
  • تاريخ الإنشاء
  • مُتلَف

السؤال 2

ما طريقة دورة الحياة التي تم تصميمها لجعل النشاط مرئيًا؟

  • onPause()
  • onVisible()
  • onStart()
  • onDestroy()

السؤال 3

ما طريقة دورة الحياة التي يتم استدعاءها للتركيز على النشاط؟

  • onResume()
  • onVisible()
  • onStart()
  • onFocus()

السؤال 4

متى يتم استدعاء onCreate() في أحد الأنشطة؟

  • كل مرة يكون فيها النشاط مرئيًا للمستخدم.
  • كل مرة يعود فيها النشاط من الخلفية.
  • مرة واحدة فقط، عند إنشاء النشاط.
  • مرة واحدة فقط، عند استئناف النشاط

إرسال تطبيقك لوضع الدرجات

تحقق للتأكد من أن التطبيق يتضمن ما يلي:

  • اعتمادية على Timber في الملف build.gradle للتطبيق.
  • فئة فرعية مخصّصة من Application تبدأ بإعداد Timber في onCreate().
  • إحدى سمات هذه الفئة الفرعية المخصّصة في بيان Android.
  • طريقة تجاوز في MainActivity لجميع طرق استدعاء دورة الحياة، مع استدعاءات Timber.i() للتسجيل.

بدء الدرس التالي: 4.2: حالات مراحل الحياة المعقدة

وللحصول على روابط إلى دروس تطبيقية أخرى حول الترميز في هذه الدورة التدريبية، يُرجى الاطّلاع على الصفحة المقصودة لتطبيق الدروس التطبيقية حول الترميز Kotlin Fundamentals.