أفضل ممارسات إدارة الذاكرة

يفترض هذا المستند أنّك اتّبعت إرشادات أفضل الممارسات لتطبيقات Android ضمن إدارة الذاكرة، مثل إدارة ذاكرة تطبيقك.

مقدمة

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

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

قبل التواصل مع فريق الدعم

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

منع تسرُّب الذاكرة

اتّبِع أفضل الممارسات التالية للمساعدة في تجنب بعض الأسباب الأكثر شيوعًا لتسرُّب الذاكرة في الرمز البرمجي الذي يستخدم حِزم تطوير البرامج (SDK) من Google.

أفضل الممارسات المتعلّقة بتطبيقات Android

تأكَّد من تنفيذ كلّ ما يلي في تطبيق Android:

  1. إلغاء حجز الموارد غير المستخدَمة
  2. إلغاء تسجيل المستمعين عند عدم الحاجة إليه
  3. إلغاء المهام عند عدم الحاجة إليها
  4. إعادة توجيه طرق دورة الحياة لإلغاء حجز الموارد
  5. استخدام أحدث إصدارات حِزم تطوير البرامج (SDK)

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

إلغاء حجز الموارد غير المستخدَمة

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

إصدار مراجع "خرائط Google" القديمة في GeoSDKs

من الأخطاء الشائعة أن خريطة Google قد تتسبب في تسرُّب الذاكرة إذا تم تخزينها مؤقتًا باستخدام ميزة NavigationView أو MapView. تربط خريطة Google علاقة من 1 إلى 1 بعرض التنقل أو خريطة الخريطة التي تم استردادها منها. يجب عليك إما التأكد من أن خريطة Google ليست مخزّنة مؤقتًا، أو من إصدار المرجع عند استدعاء NavigationView#onDestroy أو MapView#onDestroy. إذا كنت تستخدم NavigationSupportFragment أو MapSupportFragment أو الجزء الخاص بك الذي يلتف حول هذه طرق العرض، يجب إصدار المرجع في Fragment#onDestroyView.

class NavFragment : SupportNavigationFragment() {

  var googleMap: GoogleMap?

  override fun onCreateView(
    inflater: LayoutInflater,
    parent: ViewGroup?,
    savedInstanceState: Bundle?,
  ): View  {
    super.onCreateView(inflater,parent,savedInstanceState)
    getMapAsync{map -> googleMap = map}
  }

  override fun onDestroyView() {
    googleMap = null
  }
}

إلغاء تسجيل المستمعين عند عدم الحاجة إليهم

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

على سبيل المثال، لنفترض أنّ تطبيقك يستخدم حزمة تطوير البرامج (SDK) للتنقّل ويستدعي أداة معالجة البيانات التالية للاستماع إلى أحداث الوصول: طريقة addArrivalListener للاستماع إلى أحداث الوصول، يجب أن تطلب أيضًا removeArrivalListener عندما لا يحتاج إلى مراقبة أحداث الوصول.

var arrivalListener: Navigator.ArrivalListener? = null

fun registerNavigationListeners() {
  arrivalListener =
    Navigator.ArrivalListener {
      ...
    }
  navigator.addArrivalListener(arrivalListener)
}

override fun onDestroy() {
  navView.onDestroy()
  if (arrivalListener != null) {
    navigator.removeArrivalListener(arrivalListener)
  }

  ...
  super.onDestroy()
}

إلغاء المهام عندما لا تكون مطلوبة

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

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

إعادة توجيه طرق مراحل النشاط لتحرير الموارد

إذا كان تطبيقك يستخدم "حزمة تطوير البرامج (SDK) لميزة "التنقل" أو "خرائط Google"، تأكَّد من إطلاق الموارد من خلال إعادة توجيه طرق مراحل النشاط (الموضحة بالخط الغامق) إلى navView. يمكنك إجراء ذلك باستخدام "NavigationView" في حزمة تطوير البرامج (SDK) للتنقّل أو MapView في "خرائط Google" أو حزمة SDK للتنقّل. يمكنك أيضًا استخدام SupportNavigationFragment أو SupportMapFragment بدلاً من استخدام NavigationView وMapView مباشرةً، على التوالي. تتعامل أجزاء الدعم مع طرق دورة الحياة.

class NavViewActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    ...
    navView = ...
    navView.onCreate(savedInstanceState)
    ...
  }

  override fun onSaveInstanceState(savedInstanceState: Bundle) {
    super.onSaveInstanceState(savedInstanceState)
    navView.onSaveInstanceState(savedInstanceState)
  }

  override fun onTrimMemory(level: Int) {
    super.onTrimMemory(level)
    navView.onTrimMemory(level)
  }

  /* Same with
    override fun onStart()
    override fun onResume()
    override fun onPause()
    override fun onConfigurationChanged(...)
    override fun onStop()
    override fun onDestroy()
  */
}

استخدام أحدث إصدارات حِزم تطوير البرامج (SDK)

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

تصحيح أخطاء تسرّب الذاكرة

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

قبل البدء، يجب أن تكون على دراية بكيفية إدارة Android للذاكرة. للحصول على معلومات، يُرجى الاطّلاع على مقالة Android نظرة عامة على إدارة الذاكرة.

لتصحيح أخطاء تسرب الذاكرة، اتّبِع هذه العملية:

  1. إعادة عرض المشكلة هذه الخطوة ضرورية لتصحيح الأخطاء.
  2. تحقَّق مما إذا كان استخدام الذاكرة متوقَّعًا. تحقق من أن الاستخدام المتزايد الذي يبدو أنه تسرب ليست في الواقع الذاكرة المطلوبة لتشغيل التطبيق.
  3. تصحيح الأخطاء على مستوى عالٍ هناك العديد من الأدوات المساعدة التي يمكنك استخدامها لتصحيح الأخطاء. تتوفّر ثلاث مجموعات أدوات عادية مختلفة للمساعدة في تصحيح أخطاء الذاكرة في Android، وهي: Android Studio وPerfetto وأدوات سطر الأوامر Android Debug Bridge (adb).
  4. التحقّق من استخدام تطبيقك للذاكرة: يمكنك الحصول على تتبُّع للقطات لأجزاء من الذاكرة وتخصيص ثم تحليلها.
  5. إصلاح تسرّبات الذاكرة:

تتناول الأقسام التالية هذه الخطوات بالتفصيل.

الخطوة 1: إعادة إظهار المشكلة

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

  • ما هي مجموعة الميزات التي تم تفعيلها؟

  • ما هي التسلسلات المحدّدة لإجراءات المستخدمين التي تؤدي إلى حدوث التسرّب؟

    • هل حاولت تكرار عمليات تفعيل هذا التسلسل؟
  • ما هي حالات دورة الحياة التي مرّ بها التطبيق؟

    • هل جرّبت عدّة تكرارات خلال مراحل دورة الحياة المختلفة؟

تأكَّد من إمكانية إعادة إنشاء المشكلة في أحدث إصدار من حِزم تطوير البرامج (SDK). قد يكون قد تم حلّ المشكلة في إصدار سابق.

الخطوة 2: التحقّق ممّا إذا كان استخدام الذاكرة للتطبيق متوقَّعًا

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

  • تسرُّب محتمل: يؤدي تفعيل السيناريو من خلال عمليات تكرار متعددة إلى زيادة في استخدام الذاكرة بمرور الوقت.

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

  • الاستخدام المتوقّع للذاكرة: يزداد استخدام الذاكرة لفترة معيّنة ثم ينخفض تدريجيًا. قد يرجع ذلك إلى ذاكرة تخزين مؤقت محدودة أو استخدام ملف تعريف ذاكرة آخر متوقّع.

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

الخطوة 3: تصحيح الأخطاء على مستوى عالٍ

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

أداة تحليل الذاكرة في Android Studio

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

عدادات ذاكرة Perfetto

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

واجهة مستخدم Perfetto

أدوات سطر أوامر جسر تصحيح أخطاء Android (adb)

إنّ الكثير مما يمكنك تتبُّعه باستخدام Perfetto يتوفّر أيضًا كأداة سطر أوامر adb يمكنك طلبها مباشرةً. في ما يلي مثالان مهمان:

  • تتيح لك ميزة Meminfo الاطّلاع على معلومات تفصيلية عن الذاكرة في وقت معيّن.

  • يوفّر Procstats بعض الإحصاءات المجمّعة المهمة بمرور الوقت.

من الإحصاءات المهمة التي يجب الاطّلاع عليها هنا هي الحد الأقصى للمساحة التي يشغلها التطبيق في الذاكرة الفعلية (maxRSS) بمرور الوقت. قد لا تكون دقة MaxPSS عالية. للاطّلاع على طريقة لزيادة الدقة، راجِع علامة adb shell dumpsys procstats --help –start-testing.

تتبُّع التخصيص

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

الخطوة 4: التحقّق من استخدام تطبيقك للذاكرة باستخدام أداة تفريغ الذاكرة

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

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

  1. تسجيل نَسخة من الذاكرة
  2. تحليل ملف "تجميع الذاكرة" للعثور على عمليات تسرُّب الذاكرة
  3. إصلاح تسرُّب الذاكرة:

لمعرفة التفاصيل، يُرجى الاطّلاع على الأقسام التالية.

تسجيل لقطة لأجزاء من الذاكرة

لتسجيل نَسخة ذاكرة، يمكنك استخدام أداة Android Debug Bridge (adb) أو أداة تحليل الذاكرة في "استوديو Android".

استخدام adb لتسجيل لقطة لأجزاء من الذاكرة

لتسجيل لقطة لأجزاء من الذاكرة باستخدام adb، يُرجى اتّباع الخطوات التالية:

  1. وصِّل جهاز Android بالكمبيوتر.
  2. افتح موجِّه الأوامر وانتقِل إلى الدليل الذي تتوفّر فيه أدوات adb.
  3. لتسجيل لقطة لأجزاء من الذاكرة، نفِّذ الأمر التالي :

    adb shell am dumpheap my.app.name $PHONE_FILE_OUT

  4. لاسترداد لقطة لأجزاء من الذاكرة، نفِّذ الأمر التالي:

    adb pull $PHONE_FILE_OUT $LOCAL_FILE.

استخدام "استوديو Android" لتسجيل لقطة لأجزاء من الذاكرة

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

تحليل لقطة لأجزاء من الذاكرة للعثور على تسرّبات الذاكرة

بعد تسجيل نَسخة ذاكرة، يمكنك استخدام أداة تحليل ملف ملف تحليل الذاكرة في "استوديو Android" لتحليلها. لإجراء ذلك، اتّبع الخطوات التالية:

  1. افتح مشروع Android في "استوديو Android".

  2. اختَر تشغيل، ثمّ اختَر ضبط تصحيح الأخطاء.

  3. افتح علامة التبويب أداة تحليل أداء Android.

  4. اختَر الذاكرة.

  5. اختَر فتح ملف "تجميع الذاكرة" واختَر ملف "تجميع الذاكرة" الذي أنشأته. يعرض أداة تحليل الذاكرة رسمًا بيانيًا لاستخدام تطبيقك للذاكرة.

  6. استخدِم الرسم البياني لتحليل ملف "تجميع الذاكرة العشوائية":

    • تحديد العناصر التي لم تعد تُستخدم.

    • تحديد العناصر التي تستهلك الكثير من الذاكرة

    • يمكنك الاطّلاع على حجم الذاكرة التي يستخدمها كل عنصر.

  7. استخدم هذه المعلومات لتضييق نطاق البحث أو العثور على مصدر تسرُّب الذاكرة وإصلاحه.

الخطوة 5: حلّ مشكلة تسرّب الذاكرة

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

أدوات تصحيح الأخطاء الأخرى

بعد إكمال هذه الخطوات، إذا لم يتم العثور على ملف برمجي يتسبب في استهلاك زايد للذاكرة وإصلاحه، جرِّب هذه الأدوات:

تصحيح أخطاء الذاكرة في الرمز الأصلي من خلال تتبُّع عمليات التخصيص

حتى إذا لم تكن تستخدِم رمزًا أصليًا مباشرةً، فإنّ العديد من مكتبات Android الشائعة تستخدِمه، بما في ذلك حِزم SDK من Google. إذا كنت تعتقد أنّ تسرُّب الذاكرة يحدث في الرمز الأصلي، تتوفر عدة أدوات يمكنك استخدامها لتصحيح أخطاء هذا الرمز. إنّ تتبُّع التخصيص باستخدام Android Studio أو heapprofd (المتوافق أيضًا مع Perfetto) هو طريقة رائعة لتحديد الأسباب المحتملة لتسرّب الذاكرة وغالبًا ما تكون أسرع طريقة لتصحيح الأخطاء.

توفّر ميزة تتبُّع التخصيص أيضًا ميزة مميّزة تتيح لك مشاركة النتائج بدون تضمين معلومات حسّاسة يمكن العثور عليها في ذاكرة عشوائية.

رصد التسريبات باستخدام LeakCanary

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

كيفية الإبلاغ عن مشاكل في حِزم تطوير البرامج (SDK) من Google

إذا جرّبت الإجراءات الواردة في هذا المستند وتشتبه في حدوث تسرُّب للذاكرة في حِزم SDK، تواصَل مع فريق دعم العملاء مع تقديم أكبر قدر ممكن من المعلومات التالية:

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

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

  • في حال توقّع حدوث تسرُّب للذاكرة الأصلية، يمكنك مشاركة ناتج تتبُّع التخصيص من heapprofd.

  • تقرير خطأ تم إنشاؤه بعد إعادة إنشاء حالة تسرُّب البيانات

  • تتبُّع تسلسل استدعاء الدوال البرمجية لأي أعطال متعلقة بالذاكرة

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