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

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

مقدمة

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

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

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

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

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

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

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

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

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

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

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

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

إزالة مراجع GoogleMap القديمة في حِزم GeoSDK

من الأخطاء الشائعة أنّ GoogleMap يمكن أن يتسبب في تسرُّب الذاكرة إذا تم تخزينه مؤقتًا باستخدام NavigationView أو MapView. ترتبط GoogleMap بعلاقة 1 إلى 1 مع NavigationView أو MapView التي يتم استرجاعها منها. يجب ضمان عدم تخزين GoogleMap مؤقتًا أو إزالة المراجع عند استدعاء 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 في حزمة تطوير البرامج للتنقّل أو MapView في "خرائط Google" أو حزمة تطوير البرامج للتنقّل. يمكنك أيضًا استخدام SupportNavigationFragment أو SupportMapFragment بدلاً من استخدام NavigationView وMapView مباشرةً، على التوالي. تعالج أجزاء الدعم إعادة توجيه methods lifecycle .

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" وPerfetto وأدوات سطر الأوامر لـ Android Debug Bridge (adb).
  4. التحقّق من استخدام تطبيقك للذاكرة: احصل على ملف "تجميع الذاكرة" وtracking allocation، ثم تحليله.
  5. إصلاح تسرب الذاكرة:

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

الخطوة 1: إعادة إنشاء المشكلة

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

عدادات الذاكرة في Perfetto

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

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

أدوات سطر الأوامر في Android Debug Bridge (adb)

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

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

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

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

تتبُّع التوزيع

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

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

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

يمكن لخدمة Android Studio رصد عمليات تسرُّب الذاكرة التي لا يمكن لنظام جمع القمامة إصلاحها. عند تسجيل ملف "تجميع الذاكرة"، يتحقّق 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 بعنوان إدارة ذاكرة تطبيقك.

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

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

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

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

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

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

تحديد عمليات تسرُّب البيانات باستخدام LeakCanary

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

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

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

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

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

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

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

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

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