يتوقّع المستخدمون أن يتم تحميل التطبيقات بسرعة وأن تكون سريعة الاستجابة. والتطبيق الذي يستغرق وقتًا طويلاً لبدء تشغيله لا يلبي هذا التوقّع وقد يخيّب آمال المستخدمين. يمكن أن يتسبب هذا النوع من التجربة السيئة في قيام المستخدم بتقييم تطبيقك بشكل سيئ على متجر Google Play أو حتى التخلي عن تطبيقك تمامًا.
تقدّم هذه الصفحة معلومات للمساعدة في تحسين وقت تشغيل تطبيقك، بما في ذلك نظرة عامة على العناصر الداخلية لعملية التشغيل، وكيفية تحليل أداء بدء التشغيل، وبعض المشاكل الشائعة في وقت البدء مع نصائح حول كيفية معالجتها.
فهم حالات بدء تشغيل التطبيق المختلفة
يمكن أن يتم تشغيل التطبيق في إحدى الحالات الثلاث التالية: التشغيل على البارد أو إعادة التشغيل البطيء أو إعادة التشغيل السريع. وتؤثر كل حالة في المدة التي يستغرقها ظهور تطبيقك للمستخدم. في التشغيل على البارد، يبدأ تطبيقك من الصفر. في الحالات الأخرى، يحتاج النظام إلى نقل التطبيق قيد التشغيل من الخلفية إلى المقدّمة.
ننصحك دائمًا بالتحسين استنادًا إلى افتراض بدء التشغيل على البارد. ويمكن أن يؤدي ذلك إلى تحسين أداء عمليات التشغيل الدافئة والساخنة أيضًا.
لتحسين تطبيقك من أجل بدء التشغيل السريع، من المفيد فهم ما يحدث على مستوى النظام والتطبيق وكيفية تفاعلهما في كل حالة من هذه الحالات.
هناك مقياسان مهمان لتحديد وقت بدء تشغيل التطبيق، وهما الوقت المُستغرَق للعرض الأولي (TTID) والوقت المُستغرَق للعرض الكامل (TTFD). يشير TTID إلى الوقت المستغرَق لعرض الإطار الأول، بينما يشير TTFD إلى الوقت المستغرَق ليصبح التطبيق تفاعليًا بالكامل. كلاهما مهمّان بالقدر نفسه، لأنّ TTID يتيح للمستخدم معرفة أنّ التطبيق قيد التحميل، وTTFD هو الوقت الذي يصبح فيه التطبيق قابلاً للاستخدام فعليًا. إذا كان أي من هذين الخيارين طويلاً جدًا، فقد يخرج المستخدم من تطبيقك قبل تحميله بالكامل.
التشغيل على البارد
يشير التشغيل على البارد إلى تشغيل التطبيق من نقطة الصفر. وهذا يعني أنّه حتى بدء هذه العملية، تنشئ عملية النظام عملية التطبيق. يحدث التشغيل على البارد في حالات مثل تشغيل تطبيقك لأول مرة منذ تشغيل الجهاز أو منذ أن أنهى النظام التطبيق.
يمثّل هذا النوع من بدء التشغيل التحدي الأكبر لتقليل وقت بدء التشغيل، لأنّ النظام والتطبيق لديهما عمل أكثر من حالات التشغيل الأخرى.
في بداية التشغيل على البارد، ينفّذ النظام المهام الثلاث التالية:
- حمِّل التطبيق وشغِّله.
- عرض نافذة بدء فارغة للتطبيق فور تشغيله
- أنشئ عملية التطبيق.
بمجرد أن ينشئ النظام عملية التطبيق، تكون عملية التطبيق مسؤولة عن المراحل التالية:
- أنشِئ عنصر التطبيق.
- ابدأ سلسلة المحادثات الرئيسية.
- أنشئ النشاط الرئيسي.
- إعداد واجهة المستخدم
- ارسم واجهة المستخدم على الشاشة.
عندما تُكمل عملية التطبيق الرسم الأول، تستبدل عملية النظام نافذة الخلفية المعروضة بالنشاط الرئيسي. في هذه المرحلة، يمكن للمستخدم البدء في استخدام التطبيق.
لمزيد من المعلومات حول مراحل التنسيق في Compose، يُرجى الاطّلاع على مراحل Jetpack Compose.
يمكن أن تظهر مشاكل في الأداء أثناء إنشاء التطبيق وإنشاء نشاط المضيف.
إنشاء التطبيقات
عند تشغيل تطبيقك، تظل نافذة البدء الفارغة على الشاشة إلى أن ينتهي النظام من رسم التطبيق للمرة الأولى. عند هذه النقطة، تستبدل عملية النظام نافذة البدء بتطبيقك، ما يتيح للمستخدم التفاعل مع التطبيق.
إذا تجاوزت Application.onCreate في تطبيقك، يستدعي النظام طريقة onCreate في عنصر تطبيقك. بعد ذلك، ينشئ التطبيق سلسلة التعليمات الرئيسية، والمعروفة أيضًا باسم سلسلة واجهة المستخدم، ويكلّفها بإنشاء نشاط مضيف التطبيق.
من هذه النقطة، تستمر العمليات على مستوى النظام والتطبيق وفقًا لمراحل نشاط التطبيق.
إنشاء النشاط
بعد أن تنشئ عملية التطبيق نشاطك، ينفّذ النشاط العمليات التالية:
- لتهيئة القيم
- يستدعي الدوال الإنشائية.
- يستدعي طريقة رد الاتصال، مثل
Activity.onCreate، المناسبة لحالة مراحل النشاط الحالية.
عادةً ما يكون لطريقة onCreate التأثير الأكبر في وقت التحميل. في
تطبيق Jetpack Compose، غالبًا ما تأتي النفقات العامة لطريقة onCreate من
التركيب الأولي. يحدث ذلك عندما يستدعي تطبيقك setContent ويستدعي الدوال المركّبة ذات المستوى الأعلى. يمكن أن تزيد هذه المدة في حال استخدام هيكلية واجهة مستخدم مفصَّلة أو معقّدة، أو دوال مركّبة تُجري عمليات حسابية ثقيلة على سلسلة التعليمات الرئيسية.
بدء التشغيل الدافئ
تتضمّن إعادة التشغيل البطيء مجموعة فرعية من العمليات التي تتم أثناء إعادة التشغيل السريع. وفي الوقت نفسه، يمثّل هذا النوع من عمليات إعادة التشغيل عبئًا أكبر من عملية إعادة التشغيل السريع. هناك العديد من الحالات المحتملة التي يمكن اعتبارها عمليات تشغيل دافئ، مثل:
يتراجع المستخدم عن تطبيقك ثم يعيد تشغيله. قد تستمر العملية في العمل، ولكن يجب أن يعيد التطبيق إنشاء النشاط من البداية باستخدام استدعاء
onCreate.يزيل النظام تطبيقك من الذاكرة، ثم يعيد المستخدم تشغيله. يجب إعادة تشغيل العملية والنشاط، ولكن يمكن أن تستفيد المهمة إلى حدّ ما من حزمة حالة المثيل المحفوظة التي تم تمريرها إلى
onCreate.
بدء سريع
تتطلّب إعادة التشغيل السريع لتطبيقك وقتًا أقل من التشغيل على البارد. في التشغيل السريع، ينقل النظام نشاط مضيف تطبيقك إلى المقدّمة. إذا كانت واجهة المستخدم في تطبيقك لا تزال في الذاكرة، يمكن للتطبيق تجنُّب تكرار تهيئة العناصر وتهيئة واجهة المستخدم وعرضها.
ومع ذلك، إذا تم إزالة بعض الذاكرة استجابةً لأحداث تقليص الذاكرة، مثل
onTrimMemory، يجب إعادة إنشاء هذه العناصر استجابةً
لحدث التشغيل السريع.
تعرض إعادة التشغيل السريع السلوك نفسه الذي يظهر على الشاشة في سيناريو التشغيل على البارد. تعرض عملية النظام شاشة فارغة حتى ينتهي التطبيق من عرض النشاط.
كيفية تحديد بدء تشغيل التطبيق في Perfetto
لتصحيح أخطاء بدء تشغيل التطبيق، من المفيد تحديد ما يتم تضمينه بالضبط في مرحلة بدء تشغيل التطبيق. لتحديد مرحلة بدء تشغيل التطبيق بالكامل في Perfetto، اتّبِع الخطوات التالية:
في Perfetto، ابحث عن الصف الذي يحتوي على المقياس المشتق "عمليات بدء تطبيق Android". إذا لم يظهر لك، حاوِل تسجيل تتبُّع باستخدام تطبيق تتبُّع النظام على الجهاز فقط.
الشكل 2. شريحة المقياس المشتقة من عمليات بدء تطبيقات Android في Perfetto انقر على الشريحة المرتبطة واضغط على m لاختيار الشريحة. تظهر أقواس حول الشريحة وتشير إلى المدة التي استغرقتها. تظهر المدة أيضًا في علامة التبويب الاختيار الحالي.
ثبِّت صف "الشركات الناشئة في مجال تطبيقات Android" بالنقر على رمز التثبيت الذي يظهر عند تمرير المؤشر فوق الصف.
انتقِل إلى الصف الذي يتضمّن التطبيق المعنيّ وانقر على الخلية الأولى لتوسيع الصف.
كبِّر سلسلة المحادثات الرئيسية، التي تظهر عادةً في أعلى الصفحة، من خلال الضغط على w (اضغط على s وa وd للتصغير والتحرّك لليسار والتحرّك لليمين على التوالي).
الشكل 3. شريحة المقياس المشتق "بدء تشغيل تطبيق Android" بجانب سلسلة التعليمات الرئيسية للتطبيق تسهّل شريحة المقاييس المشتقة معرفة ما يتم تضمينه بالضبط في بدء تشغيل التطبيق، حتى تتمكن من مواصلة تصحيح الأخطاء بمزيد من التفاصيل.
عند تحليل تطبيق Jetpack Compose، يمكنك استخدام ميزة تتبُّع الإصدار للاطّلاع على تفاصيل دقيقة حول أداء واجهة المستخدم.
انتبه بشكل خاص إلى أقسام التتبُّع ضمن سلسلة المحادثات الرئيسية التي تبدأ بـ Choreographer#doFrame. ابحث عن شرائح مثل Compose:recompose وCompose:layout وCompose:draw. توضّح لك هذه المقاييس مقدار الوقت الذي يستغرقه تطبيقك في إنشاء مكوّنات معيّنة وقياسها ووضعها ورسمها.
استخدام المقاييس لفحص عمليات بدء التشغيل وتحسينها
لتشخيص أداء وقت بدء التشغيل بشكل صحيح، يمكنك تتبُّع المقاييس التي توضّح الوقت الذي يستغرقه تطبيقك لبدء التشغيل. يوفّر Android عدة طرق لإعلامك بوجود مشكلة في تطبيقك ومساعدتك في تشخيصها.
مزايا استخدام مقاييس بدء التشغيل
يستخدم Android مقياسَي الوقت المُستغرَق للعرض الأولي (TTID) والوقت المُستغرَق للعرض الكامل (TTFD) لتحسين عمليات بدء تشغيل التطبيق في وضعَي التشغيل على البارد والتشغيل على الدافئ. يستخدم وقت تشغيل Android (ART) البيانات من هذه المقاييس لتجميع الرمز البرمجي مسبقًا بكفاءة من أجل تحسين عمليات بدء التشغيل المستقبلية.
يؤدي بدء التشغيل السريع إلى تفاعل المستخدمين بشكل أكثر استدامة مع تطبيقك، ما يقلل من حالات الخروج المبكر أو إعادة تشغيل التطبيق أو الانتقال إلى تطبيق آخر.
الوقت المستغرَق للعرض الأولي
الوقت المستغرَق للعرض الأولي (TTID) هو الوقت المستغرَق لعرض الإطار الأول
من واجهة مستخدم التطبيق. يقيس هذا المقياس الوقت الذي يستغرقه التطبيق لإنتاج
لقطته الأولى، بما في ذلك بدء العملية أثناء التشغيل على البارد، وإنشاء
النشاط أثناء التشغيل على البارد أو الدافئ، وعرض اللقطة الأولى. يساعد الحفاظ على انخفاض وقت التفاعل الأولي في تطبيقك في تحسين تجربة المستخدم من خلال السماح للمستخدمين برؤية تطبيقك يتم تشغيله بسرعة. يتم تسجيل مقياس TTID تلقائيًا لكل تطبيق من خلال إطار عمل Android. عند تحسين وقت بدء تشغيل التطبيق، ننصحك بتنفيذ
reportFullyDrawn للحصول على معلومات حتى TTFD.
يتم قياس TTID كقيمة زمنية تمثّل إجمالي الوقت المنقضي الذي يتضمّن تسلسل الأحداث التالي:
- جارٍ بدء العملية.
- جارٍ إعداد العناصر.
- جارٍ إنشاء نشاط المضيف وإعداده.
- جارٍ إعداد واجهة المستخدم.
- رسم التطبيق لأول مرة
استرداد TTID
للعثور على TTID، ابحث في أداة سطر أوامر Logcat عن سطر ناتج يحتوي على قيمة باسم Displayed. هذه القيمة هي TTID وتظهر بشكل مشابه للمثال التالي، حيث تكون قيمة TTID هي 3s534ms:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms
للعثور على TTID في "استوديو Android"، أوقِف الفلاتر في عرض Logcat من قائمة الفلاتر المنسدلة، ثم ابحث عن وقت Displayed، كما هو موضّح في الشكل 4.
يُعد تعطيل الفلاتر ضروريًا لأن خادم النظام، وليس التطبيق نفسه، هو الذي يخدم هذا السجل.
Displayed في Logcat.لا يعكس مقياس Displayed في ناتج Logcat بالضرورة
مقدار الوقت المستغرَق لتحميل جميع الموارد وعرضها. ويستبعد الموارد التي لم تتم الإشارة إليها في التركيب الأولي (مثل البيانات أو الصور التي يتم تحميلها بشكل غير متزامن) أو الموارد التي ينشئها التطبيق كجزء من عملية إعداد العناصر. ويستبعد هذه الموارد لأنّ تحميلها
هو عملية مضمّنة ولا يحظر العرض الأولي للتطبيق.
لمزيد من المعلومات حول الموارد، يُرجى الاطّلاع على الموارد في Compose.
في بعض الأحيان، يحتوي سطر Displayed في ناتج Logcat على حقل إضافي
لإجمالي الوقت، كما في المثال التالي:
ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms (total +1m22s643ms)
في هذه الحالة، يكون قياس المرة الأولى مخصّصًا فقط للنشاط الذي يتم عرضه أولاً، وهو عادةً النشاط المضيف. يبدأ قياس وقت total عند بدء عملية التطبيق، ويمكن أن يتضمّن نشاطًا آخر يبدأ أولاً ولكن لا يعرض أي شيء على الشاشة. يتم عرض قياس الوقت total فقط عندما يكون هناك فرق بين وقت النشاط الفردي وإجمالي وقت بدء التشغيل.
ننصحك باستخدام Logcat في "استوديو Android"، ولكن إذا لم تكن تستخدم "استوديو Android"، يمكنك أيضًا قياس TTID من خلال تشغيل تطبيقك باستخدام adb أمر مدير نشاط واجهة الأوامر. وفي ما يلي مثال لذلك:
adb [-d|-e|-s <serialNumber>] shell am start -S -W
com.example.app/.MainActivity
-c android.intent.category.LAUNCHER
-a android.intent.action.MAIN
يظهر مقياس Displayed في نتائج Logcat كما في السابق. تعرض نافذة المحطة الطرفية
ما يلي:
Starting: Intent
Activity: com.example.app/.MainActivity
ThisTime: 2044
TotalTime: 2044
WaitTime: 2054
Complete
الوسيطتان -c و-a اختياريتان وتتيحان لك تحديد <category> و<action>.
الوقت المستغرَق للعرض الكامل
"الوقت المستغرَق للعرض الكامل" (TTFD) هو الوقت الذي يستغرقه التطبيق ليصبح تفاعليًا للمستخدم. ويتم تسجيله على أنّه الوقت المستغرَق لعرض الإطار الأول من واجهة مستخدم التطبيق، بالإضافة إلى المحتوى الذي يتم تحميله بشكل غير متزامن بعد عرض الإطار الأولي. بشكل عام، هذا هو المحتوى الأساسي الذي يتم تحميله من الشبكة أو القرص، كما يوضّح التطبيق. بعبارة أخرى، يشمل مقياس TTFD مقياس TTID بالإضافة إلى الوقت الذي يستغرقه التطبيق ليصبح قابلاً للاستخدام. يساعد الحفاظ على انخفاض قيمة TTFD في تطبيقك على تحسين تجربة المستخدم من خلال السماح للمستخدمين بالتفاعل مع تطبيقك بسرعة.
على الرغم من أنّ النظام يمكنه تحديد مقياس TTID عندما تعرض نافذة المضيف الإطار الأولي، لا يمكنه تحديد مقياس TTFD تلقائيًا. بما أنّ التطبيقات غالبًا ما تحمّل محتواها الأساسي بشكل غير متزامن، لا يعرف النظام متى يكون التطبيق قابلاً للاستخدام بالكامل من قِبل المستخدم. لتحديد TTFD، يحتاج التطبيق إلى إرسال إشارة إلى النظام عندما يصل إلى حالة الرسم الكامل.
استرداد TTFD
للعثور على TTFD، يمكنك الإشارة إلى حالة الرسم الكامل من خلال استدعاء طريقة
reportFullyDrawn في ComponentActivity. تُعلم طريقة reportFullyDrawn بأنّ التطبيق قد تم رسمه بالكامل وأصبح في حالة قابلة للاستخدام. يشير وقت العرض الكامل إلى الوقت المنقضي من وقت تلقّي النظام لطلب تشغيل التطبيق
إلى وقت استدعاء reportFullyDrawn. في حال عدم استدعاء
reportFullyDrawn، لن يتم تسجيل أي قيمة لمقياس TTFD.
لقياس TTFD، يمكنك استدعاء reportFullyDrawn بعد رسم واجهة المستخدم وجميع البيانات بالكامل. لا تستدعِ reportFullyDrawn قبل أن يتم رسم نافذة النشاط الأول وعرضها لأول مرة كما يقيسها النظام، لأنّ النظام سيعرض الوقت الذي يقيسه النظام. بعبارة أخرى، إذا طلبت
reportFullyDrawn قبل أن يرصد النظام مقياس TTID، سيعرض النظام كلاً من
TTID وTTFD بالقيمة نفسها، وهذه القيمة هي قيمة TTID.
عند استخدام reportFullyDrawn، تعرض أداة Logcat نتيجة مثل المثال التالي، حيث يكون TTFD هو 1s54ms:
system_process I/ActivityManager: Fully drawn {package}/.MainActivity: +1s54ms
يتضمّن ناتج Logcat أحيانًا وقت total، كما هو موضّح في الوقت المستغرَق للعرض الأولي.
إذا كانت أوقات العرض أبطأ مما تريد، يمكنك محاولة تحديد المؤثِّرات السلبية في عملية بدء التشغيل.
يمكنك استخدام reportFullyDrawn للإشارة إلى حالة الرسم الكامل في الحالات الأساسية
التي تدرك فيها أنّه تم تحقيق حالة الرسم الكامل. ومع ذلك، في الحالات التي يجب فيها أن تُكمل سلاسل العمليات في الخلفية عملها قبل الوصول إلى حالة الرسم الكامل، عليك تأخير reportFullyDrawn للحصول على قياس أكثر دقة لوقت الرسم الكامل. لمعرفة كيفية تأخير reportFullyDrawn، يُرجى الاطّلاع على القسم التالي.
تحسين دقة توقيت بدء التشغيل
إذا كان تطبيقك ينفّذ التحميل الكسول ولا يتضمّن العرض الأولي جميع الموارد، مثلاً عندما يجلب تطبيقك الصور من الشبكة، قد تحتاج إلى تأخير استدعاء reportFullyDrawn إلى ما بعد أن يصبح تطبيقك قابلاً للاستخدام حتى تتمكّن من تضمين تعبئة القائمة كجزء من توقيت قياس الأداء.
على سبيل المثال، إذا كانت واجهة المستخدم تحتوي على قائمة ديناميكية، مثل LazyColumn أو LazyRow، قد تتم تعبئتها من خلال مهمة في الخلفية تكتمل بعد رسم القائمة لأول مرة، وبالتالي بعد وضع علامة على واجهة المستخدم بأنّها مرسومة بالكامل. وفي هذه الحالات، لا يتم تضمين عدد مستخدمي القائمة في قياس الأداء.
لتضمين تعبئة القائمة كجزء من توقيت قياس الأداء، يمكنك الحصول على
FullyDrawnReporter باستخدام fullyDrawnReporter، وإضافة
مُبلِغ إليه في رمز تطبيقك. يجب تحرير أداة إعداد التقارير بعد انتهاء مهمة الخلفية
من تعبئة القائمة.
لا يستدعي FullyDrawnReporter طريقة reportFullyDrawn إلا بعد إطلاق جميع المراسلين المضافين. من خلال إضافة أداة إعداد تقارير وعدم إصدارها حتى تكتمل العملية في الخلفية، يمكنك التأكّد من أنّ بيانات توقيت بدء التشغيل تتضمّن وقت تعبئة القائمة، بدون تغيير سلوك التطبيق للمستخدم. لا يتم استدعاء reportFullyDrawn إلا بعد اكتمال جميع المهام، بغض النظر عن الترتيب.
إذا كان تطبيقك يستخدم Jetpack Compose، يمكنك استخدام واجهات برمجة التطبيقات التالية للإشارة إلى حالة الرسم الكامل:
-
ReportDrawn: تشير إلى أنّ الدالة المركّبة جاهزة فورًا للتفاعل. -
ReportDrawnWhen: تأخذ دالة شرطية، مثلlist.count > 0، للإشارة إلى أنّ الدالة المركّبة جاهزة للتفاعل. ReportDrawnAfter: تستخدم طريقة تعليق تشير، بعد اكتمالها، إلى أنّ الدالة المركّبة جاهزة للتفاعل.
يوضّح المثال التالي كيفية تشغيل مهام متعددة في الخلفية في الوقت نفسه، مع تسجيل كل مهمة لتقريرها الخاص:
class MainActivity : ComponentActivity() {
sealed interface ActivityState {
data object LOADING : ActivityState
data object LOADED : ActivityState
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
var activityState by remember {
mutableStateOf(ActivityState.LOADING as ActivityState)
}
fullyDrawnReporter.addOnReportDrawnListener {
activityState = ActivityState.LOADED
}
ReportFullyDrawnTheme {
when(activityState) {
is ActivityState.LOADING -> {
// Display the loading UI.
}
is ActivityState.LOADED -> {
// Display the full UI.
}
}
}
SideEffect {
fullyDrawnReporter.addReporter()
lifecycleScope.launch(Dispatchers.IO) {
// Perform the background operation.
fullyDrawnReporter.removeReporter()
}
fullyDrawnReporter.addReporter()
lifecycleScope.launch(Dispatchers.IO) {
// Perform the background operation.
fullyDrawnReporter.removeReporter()
}
}
}
}
}
تحديد المشاكل التي تعيق الأداء
للبحث عن حالات البطء، يمكنك استخدام "محلّل وحدة المعالجة المركزية" في "استوديو Android". لمزيد من المعلومات، يُرجى الاطّلاع على فحص نشاط وحدة المعالجة المركزية (CPU) باستخدام محلّل وحدة المعالجة المركزية (CPU).
يمكنك أيضًا الحصول على إحصاءات حول المشاكل المحتملة من خلال التتبُّع المضمّن داخل إجراءات onCreate الخاصة بتطبيقاتك وأنشطتك. للتعرّف على التتبّع المضمّن، يُرجى الاطّلاع على مستندات دوال Trace ونظرة عامة على تتبّع النظام.
حلّ المشاكل الشائعة
يتناول هذا القسم العديد من المشاكل التي تؤثر غالبًا في أداء بدء تشغيل التطبيق. تتعلّق هذه المشاكل بشكل أساسي بتهيئة عناصر التطبيق والنشاط، بالإضافة إلى تحميل الشاشات.
تهيئة التطبيق بشكل مكثّف
قد يتأثر أداء تشغيل التطبيق سلبًا عندما يتجاوز الرمز البرمجي الكائن Application
وينفّذ مهامًا ثقيلة أو منطقًا معقّدًا عند إعداد هذا الكائن. قد يضيع وقت تطبيقك أثناء بدء التشغيل إذا كانت الفئات الفرعية Application تنفّذ عمليات تهيئة لا يلزم إجراؤها بعد.
قد تكون بعض عمليات الإعداد غير ضرورية على الإطلاق، مثل إعداد معلومات الحالة للنشاط الرئيسي عندما يتم تشغيل التطبيق استجابةً لطلب معيّن. باستخدام نية، يستخدم التطبيق مجموعة فرعية فقط من بيانات الحالة التي تمت تهيئتها مسبقًا.
تشمل التحديات الأخرى أثناء إعداد التطبيق أحداث تجميع الموارد المهملة التي تكون مؤثرة أو عديدة، أو عمليات الإدخال/الإخراج على القرص التي تحدث بالتزامن مع عملية الإعداد، ما يؤدي إلى حظر عملية الإعداد بشكل أكبر. يُعدّ تجميع المهملات من الاعتبارات المهمة في وقت تشغيل Dalvik، بينما يؤدي وقت تشغيل Android (ART) إلى تجميع المهملات بشكل متزامن، ما يقلل من تأثير هذه العملية.
تشخيص المشكلة
يمكنك استخدام تتبُّع الإجراءات أو التتبُّع المضمّن لمحاولة تشخيص المشكلة.
تتبُّع الإجراءات
يكشف تشغيل "محلّل وحدة المعالجة المركزية (CPU)" أنّ الطريقة callApplicationOnCreate تستدعي في النهاية الطريقة com.example.customApplication.onCreate. إذا
أظهرت الأداة أن هذه الطرق تستغرق وقتًا طويلاً لإنهاء التنفيذ،
فاستكشف المزيد لمعرفة العمل الذي يحدث هناك.
التتبُّع المضمّن
استخدِم التتبُّع المضمّن للتحقيق في الأسباب المحتملة، بما في ذلك ما يلي:
- دالة
onCreateالأولية لتطبيقك - أي عناصر فردية عامة تتم تهيئتها في تطبيقك
- أي عمليات إدخال/إخراج على القرص أو إلغاء تسلسل أو تكرار حلقي ضيق قد تحدث أثناء الاختناق.
حلول للمشكلة
Whether the problem lies with unnecessary initializations or with disk I/O, the solution is lazy initialization. بعبارة أخرى، يجب فقط إعداد العناصر التي تحتاج إليها على الفور. بدلاً من إنشاء عناصر ثابتة عامة، يمكنك الانتقال إلى نمط أحادي حيث يبدأ التطبيق العناصر فقط في المرة الأولى التي يحتاج إليها.
ننصحك أيضًا باستخدام إطار عمل حقن التبعية، مثل Hilt، الذي ينشئ العناصر والتبعيات عند حقنها لأول مرة.
إذا كان تطبيقك يستخدم أدوات توفير المحتوى لإعداد مكوّنات التطبيق عند بدء التشغيل، ننصحك باستخدام مكتبة بدء تشغيل التطبيق بدلاً من ذلك.
بدء نشاط مكثّف
غالبًا ما يتطلّب إنشاء الأنشطة الكثير من العمل الذي يتطلّب موارد كثيرة. غالبًا ما تكون هناك فرص لتحسين هذا العمل من أجل تحقيق تحسينات في الأداء. وتشمل هذه المشاكل الشائعة ما يلي:
- تهيئة واجهة مستخدم كبيرة أو معقدة
- عمليات الإعداد المكثّفة في الدوال المركّبة
- حظر رسم الشاشة على القرص أو عمليات الإدخال/الإخراج في الشبكة
- تحميل الصور النقطية وفك ترميزها
- جارٍ تنقيط
VectorDrawableعنصر. - بدء تشغيل الأنظمة الفرعية الأخرى لنشاط مضيف التطبيق
تشخيص المشكلة
في هذه الحالة أيضًا، يمكن أن يكون كل من تتبُّع الإجراءات والتتبُّع المضمّن مفيدًا.
تتبُّع الإجراءات
عند استخدام "محلّل وحدة المعالجة المركزية"، انتبه إلى دوال الإنشاء للفئات الفرعية Application
والطرق com.example.customApplication.onCreate في تطبيقك.
إذا أظهرت الأداة أنّ هذه الطرق تستغرق وقتًا طويلاً لإكمال التنفيذ، يمكنك استكشاف المزيد لمعرفة العمل الذي يحدث هناك.
التتبُّع المضمّن
استخدِم التتبُّع المضمّن للتحقيق في الأسباب المحتملة، بما في ذلك ما يلي:
- دالة
onCreateالأولية لتطبيقك - أي عناصر فردية عامة تتم تهيئتها
- أي عمليات إدخال/إخراج على القرص أو إلغاء تسلسل أو تكرار حلقي ضيق قد تحدث أثناء الاختناق.
حلول للمشكلة
هناك العديد من المشاكل المحتملة، ولكن هناك مشكلتان شائعتان وحلول لهما على النحو التالي:
- كلما زاد حجم التسلسل الهرمي لواجهة المستخدم، زاد الوقت الذي يستغرقه التطبيق في إعداده.
يُرجى اتّباع الخطوات التالية لحلّ هذه المشكلة:
- يمكنك تبسيط التسلسل الهرمي لواجهة المستخدم من خلال تقليل الدوال المركّبة المكرّرة أو المدمجة.
- تجنَّب الإنشاء وإعادة الإنشاء غير الضروريين أثناء التشغيل.
- تأجيل إنشاء واجهة المستخدم غير الضرورية
- ويمكن أن يؤدي أيضًا إجراء جميع عمليات إعداد الموارد في سلسلة التعليمات الرئيسية إلى إبطاء بدء التشغيل. يمكنك معالجة هذه المشكلة على النحو التالي:
- انقل جميع عمليات إعداد الموارد حتى يتمكّن التطبيق من تنفيذها بشكل كسول في سلسلة محادثات مختلفة.
- حمِّل واجهة المستخدم واعرضها باستخدام بيانات العناصر النائبة أولاً، ثم عدِّل لاحقًا الخصائص المرئية التي تعتمد على الصور النقطية والموارد الأخرى.
لمزيد من المعلومات حول إعادة الإنشاء، يُرجى الاطّلاع على إعادة الإنشاء والحصول على عدد عمليات إعادة الإنشاء.
شاشات البداية المخصّصة
قد تلاحظ إضافة وقت إضافي أثناء بدء التشغيل إذا سبق لك استخدام إحدى الطرق التالية لتنفيذ شاشة بداية مخصّصة في Android 11 (المستوى 30 لواجهة برمجة التطبيقات) أو الإصدارات الأقدم:
- استخدام سمة المظهر
windowDisablePreviewلإيقاف الشاشة الفارغة الأولية التي يرسمها النظام أثناء التشغيل - استخدام
Activityمخصّص
بدءًا من الإصدار Android 12، يجب نقل البيانات إلى واجهة برمجة التطبيقات SplashScreen.
تتيح واجهة برمجة التطبيقات هذه بدء التشغيل بشكل أسرع وتسمح لك بتعديل شاشة البداية بالطرق التالية:
- اضبط مظهرًا لتغيير شكل شاشة البداية.
- يمكنك التحكّم في مدة عرض شاشة البداية باستخدام
windowSplashScreenAnimationDuration. - يمكنك تخصيص الصورة المتحركة لشاشة البداية والتعامل بسلاسة مع الصورة المتحركة لإغلاق شاشة البداية.
بالإضافة إلى ذلك، تنقل مكتبة التوافق واجهة برمجة التطبيقات SplashScreen إلى الإصدارات السابقة لإتاحة التوافق مع الأنظمة القديمة وإنشاء مظهر وأسلوب متّسقَين لعرض شاشة البداية في جميع إصدارات Android.
يُرجى الاطّلاع على دليل نقل بيانات شاشة البداية لمزيد من التفاصيل.
التطبيقات المقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما يكون JavaScript غير مفعَّل
- عرض بطيء
- تسجيل مقاييس Macrobenchmark
- إنشاء ملفات شخصية أساسية{:#creating-profile-rules}