يتوقّع المستخدمون أن يتم تحميل التطبيقات بسرعة وأن تكون متجاوبة. إذا كان وقت بدء تشغيل التطبيق طويلاً، فإنّه لن يلبي هذا التوقع وقد يؤدي إلى إحباط المستخدمين. ويمكن أن تؤدي هذه التجربة السيئة إلى تقييم المستخدم لتطبيقك بشكل سلبي على "متجر 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 الحيوية" إلى حدوث مشكلة، كما يمكن أن تساعدك أدوات التشخيص في تحديد المشكلة.
مزايا استخدام مقاييس الشركات الناشئة
يستخدم نظام التشغيل Android مقياسَي الوقت المُستغرَق للعرض الأولي (TTID) والوقت المُستغرَق للعرض الكامل (TTFD) لتحسين عمليات بدء تشغيل التطبيقات الباردة والدافئة. يستخدم وقت تشغيل Android (ART) البيانات من هذه المقاييس لإجراء عملية تجميع مسبق فعّالة للرمز البرمجي بهدف تحسين عمليات بدء التشغيل المستقبلية.
تؤدي عمليات بدء التشغيل الأسرع إلى تفاعل مستخدم أكثر استدامة مع تطبيقك، ما يقلّل من حالات الخروج المبكر أو إعادة تشغيل المثيل أو الانتقال إلى تطبيق آخر.
مؤشرات Android الحيوية
يمكن أن تساعد "مؤشرات Android الحيوية" في تحسين أداء تطبيقك من خلال تنبيهك على Play Console عندما تكون أوقات بدء تشغيل تطبيقك مفرطة.
تعتبر "مؤشرات Android الحيوية" أوقات بدء التشغيل التالية لتطبيقك مفرطة:
- يستغرق بدء التشغيل على البارد 5 ثوانٍ أو أكثر.
- يستغرق بدء التشغيل الدافئ ثانيتَين أو أكثر.
- يستغرق بدء التشغيل من الخلفية بعد فترة قصيرة مدة 1.5 ثانية أو أكثر.
تستخدِم "مؤشرات Android الحيوية" مقياس الوقت المُستغرَق للعرض الأولي (TTID). للحصول على معلومات حول طريقة جمع Google Play لبيانات "مؤشرات Android الحيوية"، يُرجى الاطّلاع على مستندات Play Console.
الوقت المُستغرَق للعرض الأولي
يشير مصطلح "الوقت المستغرَق للعرض الأولي" (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 shell الخاص بمدير الأنشطة. وفي ما يلي مثال لذلك:
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 بالإضافة إلى الوقت الذي يستغرقه التطبيق ليصبح قابلاً للاستخدام. يساعد الحفاظ على انخفاض وقت التفاعل الأول في تطبيقك في تحسين تجربة المستخدم من خلال السماح للمستخدمين بالتفاعل مع تطبيقك بسرعة.
على الرغم من أنّ النظام يمكنه تحديد TTID عندما تعرض نافذة المضيف إطارها الأوّلي، لا يمكنه تحديد TTFD تلقائيًا. بما أنّ التطبيقات غالبًا ما تحمّل محتواها الأساسي بشكل غير متزامن، لا يعرف النظام متى يصبح التطبيق قابلاً للاستخدام بشكل كامل من قِبل المستخدم. لتحديد TTFD، يجب أن يرسل التطبيق إشارة إلى النظام عند وصوله إلى حالة الرسم الكامل.
استرداد TTFD
للعثور على مقياس TTFD، أشِر إلى حالة الرسم الكامل من خلال استدعاء طريقة
reportFullyDrawn الخاصة بـ ComponentActivity. تعرض الطريقة
reportFullyDrawn الوقت الذي يتم فيه رسم التطبيق بالكامل ويكون في حالة
قابلة للاستخدام. يشير TTFD إلى الوقت المنقضي منذ أن يتلقّى النظام نية تشغيل التطبيق إلى أن يتم استدعاء reportFullyDrawn. إذا لم تستدعِ
reportFullyDrawn، لن يتم تسجيل أي قيمة لسمة TTFD.
لقياس TTFD، استدعِ الدالة reportFullyDrawn بعد رسم واجهة المستخدم والبيانات بالكامل. لا تستدعِ الدالة reportFullyDrawn قبل أن يتم رسم نافذة النشاط الأول وعرضها لأول مرة كما يقيسها النظام، لأنّ النظام سيُبلغ حينها عن الوقت الذي قاسه. بعبارة أخرى، إذا طلبت
reportFullyDrawn قبل أن يرصد النظام TTID، سيُبلغ النظام عن كل من
TTID وTTFD بالقيمة نفسها، وهذه القيمة هي قيمة TTID.
عند استخدام reportFullyDrawn، تعرض أداة Logcat نتيجة مشابهة للمثال التالي، حيث يبلغ وقت التفاعل الأول 1 ثانية و54 ملي ثانية:
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()
}
}
}
}
}
تحديد المشاكل التي تؤدي إلى بطء الأداء
للبحث عن نقاط الاختناق، يمكنك استخدام أداة CPU Profiler في "استوديو Android". لمزيد من المعلومات، يُرجى الاطّلاع على فحص نشاط وحدة المعالجة المركزية باستخدام أداة CPU Profiler.
يمكنك أيضًا الحصول على إحصاءات حول المشاكل المحتملة من خلال التتبُّع المضمّن
داخل طرق onCreate الخاصة بتطبيقاتك وأنشطتك. لمزيد من المعلومات حول التتبُّع المضمّن، راجِع مستندات وظائف Trace ونظرة عامة
على تتبُّع النظام.
حلّ المشاكل الشائعة
يتناول هذا القسم العديد من المشاكل التي تؤثر غالبًا في أداء بدء تشغيل التطبيق. تتعلّق هذه المشاكل بشكل أساسي بتهيئة عناصر التطبيق والنشاط، بالإضافة إلى تحميل الشاشات.
بدء تشغيل التطبيق بشكل مكثّف
قد يتأثر أداء التشغيل سلبًا عندما يتجاوز الرمز البرمجي العنصر Application
وينفّذ عمليات مكثّفة أو منطقًا معقّدًا عند تهيئة هذا العنصر. قد يضيع تطبيقك الوقت أثناء بدء التشغيل إذا كانت الفئات الفرعية Application تنفّذ عمليات تهيئة لا يلزم إجراؤها بعد.
قد تكون بعض عمليات التهيئة غير ضرورية تمامًا، مثل تهيئة معلومات الحالة للنشاط الرئيسي عندما يتم بدء تشغيل التطبيق استجابةً لغرض. باستخدام Intent، لا يستخدم التطبيق سوى مجموعة فرعية من بيانات الحالة التي تم تهيئتها سابقًا.
تشمل التحديات الأخرى أثناء تهيئة التطبيق أحداث جمع البيانات المُهمَلة التي تكون مؤثرة أو عديدة، أو عمليات وحدات الإدخال والإخراج على القرص التي تحدث بشكل متزامن مع عملية التهيئة، ما يؤدي إلى حظر عملية التهيئة بشكل أكبر. وتُعد عملية جمع البيانات المُهمَلة من الاعتبارات المهمة بشكل خاص في وقت تشغيل Dalvik، بينما ينفّذ وقت تشغيل Android (ART) عملية جمع البيانات المُهمَلة بشكل متزامن، ما يقلّل من تأثير هذه العملية.
تشخيص المشكلة
يمكنك استخدام تتبُّع الأسلوب أو التتبُّع المضمّن لمحاولة تشخيص المشكلة.
تتبُّع الإجراءات
يؤدي تشغيل أداة "محلّل أداء وحدة المعالجة المركزية" إلى الكشف عن أنّ الطريقة callApplicationOnCreate تستدعي في النهاية الطريقة com.example.customApplication.onCreate. إذا أظهرت الأداة أنّ تنفيذ هذه الطرق يستغرق وقتًا طويلاً، يمكنك استكشاف المزيد لمعرفة العمليات التي تحدث هناك.
التتبُّع المضمّن
استخدِم التتبُّع المضمّن للتحقيق في الأسباب المحتملة، بما في ذلك ما يلي:
- تمثّل هذه السمة وظيفة تطبيقك الأولية
onCreate. - أي عناصر سينغلتون عامة يبدأ تطبيقك في تهيئتها
- أي عمليات إدخال/إخراج للقرص أو إلغاء تسلسل أو حلقات ضيقة قد تحدث أثناء عنق الزجاجة
حلول للمشكلة
سواء كانت المشكلة مرتبطة بعمليات إعداد غير ضرورية أو بعمليات إدخال/إخراج على القرص، فإنّ الحلّ هو الإعداد المؤجّل. بعبارة أخرى، لا تبدأ في إنشاء الكائنات إلا عند الحاجة إليها بشكل فوري. بدلاً من إنشاء عناصر ثابتة عامة، انتقِل إلى نمط كائن فردي حيث يبدأ التطبيق في تهيئة العناصر عند الحاجة إليها للمرة الأولى فقط.
ننصحك أيضًا باستخدام إطار عمل لإدخال التبعيات مثل Hilt الذي ينشئ العناصر والاعتماديات عند إدخالها لأول مرة.
إذا كان تطبيقك يستخدم موفّري المحتوى لتهيئة مكوّنات التطبيق عند بدء التشغيل، ننصحك باستخدام مكتبة "بدء تشغيل التطبيق" بدلاً من ذلك.
بدء النشاط الذي يتطلّب مجهودًا كبيرًا
يتطلّب إنشاء الأنشطة في كثير من الأحيان الكثير من العمل الذي يتضمّن تكاليف عامة مرتفعة. في كثير من الأحيان، تتوفّر فرص لتحسين هذا العمل من أجل تحقيق تحسينات في الأداء. وتشمل المشاكل الشائعة ما يلي:
- تهيئة واجهة مستخدم كبيرة أو معقّدة
- عمليات تهيئة مكثّفة في الدوال البرمجية القابلة للإنشاء
- حظر رسم الشاشة على القرص أو إدخال/إخراج البيانات من الشبكة
- تحميل صور نقطية وفك ترميزها
- تحويل عناصر
VectorDrawableإلى صور نقطية - تهيئة الأنظمة الفرعية الأخرى لنشاط المضيف الخاص بالتطبيق
تشخيص المشكلة
في هذه الحالة أيضًا، يمكن أن يكون تتبُّع الطريقة وتتبُّع التعليمات البرمجية المضمّنة مفيدًا.
تتبُّع الإجراءات
إذا أظهرت الأداة أنّ تنفيذ هذه الطرق يستغرق وقتًا طويلاً، يمكنك استكشاف المزيد لمعرفة العمليات التي تحدث هناك.
التتبُّع المضمّن
استخدِم التتبُّع المضمّن للتحقيق في الأسباب المحتملة، بما في ذلك ما يلي:
- تشير إلى
onCreateالوظيفة الأولية لتطبيقك. - أي عناصر فردية عامة تتم تهيئتها
- أي عمليات إدخال/إخراج للقرص أو إلغاء تسلسل أو حلقات ضيقة قد تحدث أثناء عنق الزجاجة
حلول للمشكلة
هناك العديد من المشاكل المحتملة التي تؤدي إلى بطء الأداء، ولكن إليك مشكلتين شائعتين مع الحلول المقترَحة:
- كلما كان تسلسل واجهة المستخدم أكبر، استغرق التطبيق وقتًا أطول لضبطه.
يُرجى مراعاة الخطوات التالية عند معالجة هذه المشكلة:
- يمكنك تسوية بنية واجهة المستخدم الهرمية من خلال تقليل العناصر القابلة للإنشاء المكرّرة أو المتداخلة.
- تجنَّب عمليات الإنشاء وإعادة الإنشاء غير الضرورية أثناء التشغيل.
- تأجيل إنشاء عناصر واجهة المستخدم غير المهمة
- يمكن أن يؤدي تنفيذ جميع عمليات تهيئة الموارد في سلسلة التعليمات الرئيسية إلى إبطاء عملية بدء التشغيل أيضًا. يمكنك معالجة هذه المشكلة باتّباع الخطوات التالية:
- انقل جميع عمليات تهيئة الموارد حتى يتمكّن التطبيق من تنفيذها بشكل مؤجّل في سلسلة محادثات مختلفة.
- حمِّل واعرض واجهة المستخدم مع بيانات العناصر النائبة أولاً، ثم عدِّل لاحقًا الخصائص المرئية التي تعتمد على الصور النقطية والموارد الأخرى.
لمزيد من المعلومات حول إعادة التكوين، راجِع إعادة التكوين والحصول على عدد عمليات إعادة التكوين.
شاشات البداية المخصّصة
قد تلاحظ إضافة وقت إضافي أثناء بدء التشغيل إذا سبق لك استخدام إحدى الطرق التالية لتنفيذ شاشة بداية مخصّصة في Android 11 (المستوى 30 لواجهة برمجة التطبيقات) أو إصدار أقدم:
- استخدام سمة المظهر
windowDisablePreviewلإيقاف الشاشة البيضاء الأولية التي يرسمها النظام أثناء التشغيل - استخدام
Activityمخصّص
اعتبارًا من Android 12، يجب الانتقال إلى واجهة برمجة التطبيقات SplashScreen.
تتيح واجهة برمجة التطبيقات هذه بدء التشغيل بشكل أسرع وتتيح لك تعديل شاشة البداية بالطرق التالية:
- ضبط مظهر لتغيير مظهر شاشة البداية
- التحكّم في مدة عرض شاشة البداية باستخدام
windowSplashScreenAnimationDuration - خصِّص الصورة المتحركة في شاشة البداية، وتعامل مع الصورة المتحركة لإغلاق شاشة البداية بشكل سليم.
بالإضافة إلى ذلك، تنقل مكتبة التوافق وظيفة SplashScreen API إلى الإصدارات القديمة من نظام التشغيل لتوفير التوافق مع الإصدارات القديمة وإنشاء مظهر موحّد لشاشة البداية على جميع إصدارات Android.
راجِع دليل نقل البيانات الخاص بشاشة البداية للاطّلاع على التفاصيل.
اقتراحات مخصصة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون JavaScript غير مفعّلة.
- العرض البطيء
- تسجيل مقاييس Macrobenchmark
- إنشاء ملفات تعريف أساسية{:#creating-profile-rules}