English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
مثال هذا المقال يشرح كيفية معالجة انفجار ذاكرة التطبيقات في تطوير Android وطرق منعها. يشارك معكم ونأمل أن تكون مفيدًا، مثلما يلي:
مستضيف محرك Android قائم على السجلات Dalvik، حجم الحجم الأقصى للسلة العامة يكون عادة 16M. ولكن لأن Android مكتوب بلغة Java، لذا فإن ميكانيكية ذاكرة Android تعادل إلى حد كبير ميكانيكية ذاكرة Java، مما يؤدي إلى مشاكل محدودة في الذاكرة عند بدء التطوير، يمكن أن نواجه مشاكل تجاوز الذاكرة الشديدة. عند عدم استخدام بعض الذاكرة، يجب علينا أن نحاول تجنب الحفاظ على الحالة الضرورية في Android أو منصات أخرى عند تشغيل برامج أخرى، مما يؤدي إلى مشاكل ذاكرة العمليات الميتة، يجب أن نحرر هذه الحالة عند إغلاق التطبيق أو حفظ الحالة، مما يمكن أن يزيد من سلاسة تشغيل النظام.
تظهر ذاكرة Android بشكل رئيسي في:
في منصة Android، يمكن أن يؤدي الحفاظ على مراجع بعض الموارد لفترة طويلة إلى عدم إمكانية إطلاق بعض الذاكرة، مما يؤدي إلى مشاكل تسرب الذاكرة. على سبيل المثال: السياق (في النص اللاحق، جميع النشاطات المذكورة هي سياق)، عند الحاجة إلى الحفاظ على حالة نموذج أولي ومرور هذه الحالة إلى نموذج آخر، يجب أولاً تحرير النموذج المقبل قبل إزالة النموذج الأولي. يجب الانتباه إلى نقطة واحدة: لأن في ميكانيكية ذاكرة Java أو Android، يجب التأكد من عدم استدعاء أي عنصر آخر قبل تحرير العنصر الذري قبل أن يتم استرداده من قبل نظام GC. لنرى كودًا:
@Override protected void onCreate(Bundle state) { super.onCreate(state); TextView label = new TextView(this); label.setText("Leaks are bad"); setContentView(label); {}
معنى هذا الكود هو أننا نحمل نموذج TextView في النشاط (السياق) الذي نقوم بتنفيذه، لذا، من خلال آلية استعادة الذاكرة (GC)، نعلم أن لتحرير السياق، يجب أولاً تحرير بعض العناصر التي يستخدمها، وإلا فإنك ستجد أن هناك الكثير من تجاوزات الذاكرة عند محاولة تحرير السياق. لذا، يمكن أن يكون تجاوز الذاكرة أمرًا سهلاً عندما تحدث بالخطأ. عند حفظ بعض العناصر، يمكن أيضًا أن يؤدي إلى تسرب الذاكرة. بسيط جدًا مثل Bitmap، على سبيل المثال: عند تحويل الشاشة، يمكن أن يتم تدمير حالة النشاط الحالية التي يتم الحفاظ عليها، وأن يتم طلب إنشاء نشاط جديد، حتى يتم حفظ حالة النشاط الجديد. لنرى كودًا آخر:
private static Drawable sBackground; @Override protected void onCreate(Bundle state) { super.onCreate(state); TextView label = new TextView(this); label.setText("Leaks are bad"); if (sBackground == null) { sBackground = getDrawable(R.drawable.large_bitmap); {} label.setBackgroundDrawable(sBackground); setContentView(label); {}
هذا الكود سريع جدًا ولكن خطأ. يمكن أن يحدث تسرب الذاكرة بسهولة عند تغيير اتجاه الشاشة. على الرغم من أننا قد نلاحظ أننا لم نحفظ مثيل سياق هذا، ولكن عندما نربط رسمًا برؤية، يتم تعيين Drawable إلى View كإعادة التشغيل، مما يعني أننا، في الكود المذكور أعلاه، نحن بالفعل نستخدم هذا النشاط (Activity). يمكن أن يتم التعبير عن الربط كالتالي: Drawable->TextView->Context.
لذلك، عندما تريد إطلاق سياق (Context)، فإنه لا يزال محفوظًا في الذاكرة وليس متاحًا لإطلاقه.
كيف يمكن تجنب هذا الحالةهذا يعتمد بشكل رئيسي على. يمكن أن يحدث خطأ في السطر سهل. لا تدعو للتفكير في السطور، لأنها يمكن أن تسبب تسرب الذاكرة في Android بسهولة. السبب الرئيسي لتسرب الذاكرة في السطور هو أن دورة حياة السطر غير قابلة للتحكم فيها. إليك قطعة من الكود:
public class MyTest extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); new MyThread().start(); {} private class MyThread extends Thread{ @Override public void run() { super.run(); //قم بشيء {} {} {}
الكود بسيط، ولكن هناك مشكلة جديدة في Android، عندما ننتقل بين شاشات العرض (أفقية أو عمودية)، يتم إنشاء نشاط الهاتف الذكي (Activity) الجديد مرة أخرى. نعتقد بشكل تصوري أن النشاط الذي تم إنشاؤه مسبقًا سيتم إزالته، ولكن كيف هي الحقيقة؟ لا يقدم لك ميكانيكية Java نفس الشعور، لأن وظيفة run لم تنته بعد، لذا لم يتم تدمير MyThread، مما يعني أن النشاط الذي يشير إليه (Mytest) لم يتم تدميره أيضًا، مما يؤدي أيضًا إلى مشكلة تسرب الذاكرة.
بعض الناس يفضلون استخدام AsyncTask التي يقدمها Android، ولكن في الواقع مشكلة AsyncTask أكثر خطورة، Thread يظهر مشكلة تسرب الذاكرة فقط عندما لا تنتهي دالة run، ومع ذلك، يستخدم AsyncTask آلية ThreadPoolExecutor، ويكون حياة Thread الذي ينتج غير معروفة وغير قابلة للتحكم من قبل التطبيق، لذا إذا كان AsyncTask فئة داخلية لActivity، فإن مشكلة تسرب الذاكرة ستظهر بشكل أسرع.
طرق تحسين مشاكل التسلسل هي:
① قم بتغيير فئة الداخلية للصف إلى فئة داخلية ثابتة.
② حاول استخدام المراجع الضعيفة لحفظ سياق في البرنامج.
2. bitmap السيء...
Bitmap هو شيء سيء جدًا، بالنسبة لشيء في الذاكرة، إذا كان حجم الذاكرة التي يستخدمها كبيرًا، عند تجاوز حد الذاكرة النظامية، مشكلة تسرب الذاكرة تصبح واضحة.
حل مشكلة bitmap يتطلب حل مشكلة عدم حفظ الذاكرة للbitmap أو تقليل معدل التحليل. في العديد من الحالات، بسبب أن دقة صورنا مرتفعة، بينما حجم شاشة الهاتف ليس كبيرًا، يمكننا أولاً تقليل معدل التحليل للصورة قبل القيام بالعمليات UI الأصلية.
إذا لم نحتاج إلى حفظ مراجع bitmap عند عدم الحاجة إليها، يمكننا استخدام المراجع الضعيفة كبديل. هناك العديد من الأمثلة على ذلك في Google.
بشكل عام، لتجنب تسرب الذاكرة، يجب اتباع النقاط التالية بشكل رئيسي:
الأول: لا تحتفظ بالمراجع إلى سياق لفترة طويلة (إذا كنت بحاجة إلى مراجعة سياق، يجب أن تكون حياة المرجع والموضوع نفسها متساوية).
الثاني: إذا كنت بحاجة إلى استخدام سياق، حاول استخدام ApplicationContext بدلاً من سياق، لأن حياة ApplicationContext أطول، مما يقلل من مشكلة تسرب الذاكرة.
الثالث: تجنب استخدام متغيرات static في Activity عندما لا تتحكم في حياة الأشياء. حاول استخدام WeakReference بدلاً من static.
الرابع: لا يضمن محول النفايات استعادة الذاكرة بشكل دقيق، لذا عند استخدام المحتوى الذي تحتاجه، يجب أن تكون الحياة الأساسية للمحتوى الرئيسي وأن يتم إطلاق العنان للأشياء غير الضرورية في الوقت المناسب. حاول في نهاية حياة Activity، في onDestroy، إطلاق العنان للأشياء التي نقوم بتحديد إشاراتها، مثل: cursor.close().
في الواقع، يمكننا استخدام أقل كود لإنجاز البرامج في العديد من المجالات. على سبيل المثال: يمكننا استخدام صور 9patch بشكل أكبر. هناك العديد من التفاصيل التي يمكننا اكتشافها ومكشوفة أكثر من مشاكل الذاكرة. إذا استطعنا تحقيق مبدأ 'من يخلق، يتحرر' للبرامج في C/C++، فإننا لن نكون أقل من Java أو نظام التشغيل Android نفسه في التعامل مع الذاكرة، بل سنكون قادرين على التحكم في الذاكرة بشكل أفضل، مما يجعل تشغيل هاتفنا أكثر سلاسة.
يمكن للقراء المهتمين بمزيد من المعلومات المتعلقة بAndroid التحقق من المقالات الخاصة بالموقع: 'تجميع تقنيات التخزين والتخزين المؤقت في تطوير Android'، 'دليل البدء والتحسين في تطوير Android'، 'تجميع تقنيات الت调试 والاستجابة للأخطاء الشائعة في Android'، 'تجميع تقنيات التشغيل المتعدد للميديا في Android (الصوت، الفيديو، التسجيل، إلخ)'، 'تجميع استخدامات المكونات الأساسية في Android'، 'تجميع تقنيات View في Android'، 'تجميع تقنيات layout في Android'، و 'تجميع استخدامات العناصر التحكم في Android'.
آمل أن يساعدكم ما ذكرته في هذا المقال في تصميم برامج Android.
البيان: محتوى هذا المقال تم جمعه من الإنترنت، ويتمتع صاحب الحقوق الأصلية بالملكية، ويتم جمع المحتوى من قبل المستخدمين عبر الإنترنت بطرق متفرقة، ولا يمتلك هذا الموقع حقوق الملكية، ولا يتم تعديل المحتوى بشكل يدوي، ولا يتحمل هذا الموقع أي مسؤولية قانونية متعلقة بذلك. إذا اكتشفتم محتوى يشتبه في انتهاك حقوق النسخ، مرحبًا بكم في إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (يرجى استبدال # ب @ عند إرسال البريد الإلكتروني) للإبلاغ، وقدموا الأدلة ذات الصلة، وسيتم حذف المحتوى المزعوم عن انتهاك حقوق النسخ على الفور إذا تم التحقق من صحة الشكوى.