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

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

مقدمة

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

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

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

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

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

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

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

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

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

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

تحرير الموارد غير المستخدَمة

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

تحرير مراجع GoogleMap القديمة في حِزم تطوير البرامج (SDK) المستندة إلى الموقع الجغرافي

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

على سبيل المثال، إذا كان تطبيقك يستخدم حزمة تطوير البرامج للتنقّل ويستدعي المستمع التالي للاستماع إلى أحداث الوصول: 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.

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

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

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)

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

تجنُّب حظر سلسلة التعليمات الرئيسية أثناء عملية الإعداد لمنع أخطاء ANR

عندما يحظر تطبيق سلسلة التعليمات الرئيسية لفترة طويلة جدًا، يمكن أن يؤدي ذلك إلى ظهور الخطأ "التطبيق لا يستجيب" (ANR). لمنع أخطاء ANR، اجعل طرق دورة الحياة، مثل onCreate()، خفيفة قدر الإمكان من خلال تأجيل المهام التي تستغرق وقتًا طويلاً أو تشغيلها خارج سلسلة التعليمات الرئيسية.

لتجنُّب أخطاء ANR المرتبطة بإعداد حزمة تطوير البرامج (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

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

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

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

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

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

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

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

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

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

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

  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" أو heapprofd (المتوافق أيضًا مع Perfetto) طريقة رائعة لتحديد الأسباب المحتمَلة لـ تسرّب الذاكرة، وغالبًا ما تكون الطريقة الأسرع لتصحيح الأخطاء.

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

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

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

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

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

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

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

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

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

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

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