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

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

مقدمة

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

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

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

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

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

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

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

تأكّد من تنفيذ جميع الإجراءات التالية في تطبيق Android:

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

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

إلغاء الموارد غير المستخدمة

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

إصدار مراجع "خرائط Google" القديمة في حِزم GeoSDK

أحد الأخطاء الشائعة هو أن خريطة Google يمكن أن تتسبب في تسرُّب الذاكرة إذا تم تخزينها مؤقتًا باستخدام NavigationView أو MapView. تحتوي خريطة Google على علاقة 1-1 مع NavigationView أو MapView التي يتم استردادها منها. يجب عليك إما التأكد من أن خريطة 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) الخاصة بالتنقل أو الخرائط، احرص على تحرير الموارد من خلال إعادة توجيه طرق مراحل النشاط (المعروضة بالخط العريض) إلى navView. يمكنك القيام بذلك باستخدام NavigationView في حزمة SDK للتنقل أو MapView في الخرائط أو حزمة 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 باستمرار من خلال الميزات الجديدة وإصلاحات الأخطاء وتحسينات الأداء. احرِص على تحديث حِزم SDK في تطبيقك باستمرار لتلقّي هذه الإصلاحات.

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

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

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

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

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

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

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

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

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

  • ما التسلسل المحدد لإجراءات المستخدم التي تؤدي إلى تسريب المعلومات؟

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

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

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

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

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

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

  • استخدام الذاكرة المتوقع: يتم استعادة الذاكرة بعد توقف السيناريو.

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

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

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

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

محلّل الذاكرة في "استوديو Android"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  1. سجِّل نَسْخًا للذاكرة.
  2. تحليل نَسْخ الذاكرة لرصد حالات تسرّب الذاكرة
  3. إصلاح تسرُّب الذاكرة

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

تسجيل عملية تفريغ الذاكرة

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

استخدام 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 Studio لتسجيل نَسخ الذاكرة

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

تحليل نَسْخ الذاكرة لرصد المحتوى المتسرّب في الذاكرة

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

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

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

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

  4. انقر على الذاكرة.

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

  6. استخدِم الرسم البياني لتحليل نَسْخ الذاكرة:

    • تحديد الكائنات التي لم تعُد قيد الاستخدام.

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

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

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

الخطوة 5: إصلاح تسرُّب الذاكرة

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

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

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

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

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

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

رصد تسرُّب الأموال باستخدام LeakCanary

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

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

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

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

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

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

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

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

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