مفهوم الـ Context في الأندرويد

مفهوم الـ Context في الأندرويد وكيف تستخدم الـ Context الصحيح في المكان الصحيح

Mohammad Al-Aliمنذ سنة

السلام عليكم ورحمة الله وبركاته ..

إذا كنت مطور تطبيقات أندرويد فإنه لا بد وأن مر عليك مصطلح الـ Context، فهو أحد أهم المفاهيم في تطوير تطبيقات أندرويد  إذ تجده أينما تذهب! في هذه المقالة، نحاول أن نفهم ما هو الـ Context وكيف تستخدم الـ Context الصحيح في المكان الصحيح لتجنب الـ Memory Leak!

 

ما هو الـ Context؟

كما يوضّح الاسم، الـ Context (السياق) هو سياق أو حالة التطبيق الحالية، حيث يمكّن الكائنات من معرفة بعض المعلومات عن التطبيق، اسم الـ package مثلاً.

كما يساعد النظام في تحديد الـ resources ( الموجودة في مجلد الـ res) المطلوبة التابعة للتطبيق، ملفات التطبيق، قواعد البيانات، ملفات الـ SharedPreferences.

 

هناك عدة أنواع للـ Context، حيث أن الـ Activity ترث من الـ Context ويوجد أيضاً الـ ApplicationContext. لذلك من الأفضل معرفة الاستخدام الصحيح لكل نوع من الـ Contexts، لأن الاستخدام الخاطئ للـ Context قد يؤدي إلى ما يعرف بالـ Memory Leak (تسرب الذاكرة)!. ولكن ما هو الـ Memory Leak؟!

 

مفهوم الـ Memory Leak:

لكي نفهم المشكلة، تعالوا نتأكد من فهمنا لكيفية إنشاء والوصول للـ Objects في جافا. يُنشئ الكائن في جافا باستخدام الكلمة المفتاحية new، حيث يعود لنا مرجع للكائن بعد إنشاءه لكي نستطيع الوصول إليه.

لنفترض أن لدينا Class اسمه Student:

Student s;

s = new Student("Mohammad");

في السطر الأول، أنشأنا مرجع (reference) من نوع Student يمكّننا من الوصول إلى الكائن - من نوع Student - الذي نسنده له، ولكن في السطر الأول لم نسند له أي قيمة وقيمته الأولية هي null.

في السطر الثاني أنشأنا الـ Object باستخدام new وجعلنا المرجع s يشير له. والآن ماذا إذا أردنا الوصول للكائن من مكان آخر، أو تمريره لدالة معينة:

 

Student s2 = s;
s.setName("MOHAMMAD");
printStudent(s2);

في الكود السابق أنشأنا مرجع جديد من نوع Student وجعلناه يشير للكائن الذي يشير له الـ s، لذلك يمكننا الآن الوصول والتعديل على الكائن من s, s2 حيث أنهما يشيران لنفس الكائن في الذاكرة. لذلك، تمرير s أو s2 للدالة printStudent سيكون لهما نفس المخرجات.

 

الـ Garbage Collection:

ماذا لو قمنا بتغيير قيم الـ s, s2 لتشير إلى أي كائن آخر أو null :

s = new Student("Ahmad");
s2 = null;

كيف يمكننا الوصول للكائن القديم (Mohammad)؟! لقد أضعنا الكائن في الذاكرة ولا يمكننا الوصول إليه!

هل سيبقى هكذا تائه في الذاكرة إلى أن يغلق البرنامج!

بالطبع لا، فهناك من هو مسؤول عن تولي هذا الأمر، الكائن بعد أن فقدناه أصبح garbage لا فائدة منه، لذا نحتاج لتنظيف الذاكرة منه بعملية تسمى Garbage Collection  وهي عملية يقوم بها الـ GarbageCollector لتحرير الذاكرة من الـ Unreferenced objects أي الكائنات التي ليس لها reference ولا يمكن الوصول لها. تقوم آلة جافة الإفتراضية (JVM) بهذه العملية بشكل دوري كلما دعت الحاجة لذلك.

 

 

نعود لمشكلتنا، الـ Memory Leak، تحدث هذه المشكلة عندما نحتفظ في الذاكرة بكائنات لا حاجة لنا بها، ولا يمكن للـ Garbage Collector أن يحررها لأن هناك refernece/s تشير لها!

سنفهم المشكلة أكثر بتطبيقها على الـ Contexts وأنواعها.

 

Application Context:

هو Context وحيد للتطبيق حيث يعتمد نمط التصميم Singleton Design Pattern ويمكن الحصول عليه في الـ Activity باستدعاء getApplicationContext() . هذا الـ Context مرتبط بدورة حياة التطبيق، حيث يمكنك استخدامه عندما تريد Context منفصل و لا يرتبط بالـ Activity الحالية. 

أمثلة استخدام: يمكن استخدامه عندما يكون لديك Singleton Object وحيد للتطبيق ويحتاج إلى Context. مثل الكائنات الخاصة بالوصول لقواعد البيانات، جلب البيانات من السيرفر..

ولكن ماذا إذا استخدمنا Context من نوع Activity في هذه الحالات؟! 

هذا يؤدي إلى الـ Memory Leak، حيث أنه في حالة أُغلقت الـ Activity فلا يمكن أن نمسحها من الذاكرة بعملية الـ Garbage Collection لأننا أعطينا refernece لها لهذه الكائنات (في الحالات المذكورة في الأعلى) التي ستعمل طوال فترة حياة التطبيق!

 

ملاحظة: إذا كنت تنشئ ContentProvider وطلبت getContext() فإن الكائن الذي سيرجع من نوع ApplicationContext 

 

Activity Context:

هذا الـ Context مرتبط بدورة حياة الـ Activity ويجب استعماله فقط إذا أردت تمرير Context لكائن مرتبط فقط بالـ Activity.

 

ملاحظة: الـ ApplicationContext قد لا يكون كافي في بعض الأحيان وخصوصاً في الأمور المتعلقة بواجهات المستخدم UI.

 

الخلاصة:

استخدم الـ Context المتوفر لديك مباشرة في أي component تكون فيه (Activity, Service..) إلا في حالة أن الكائن الذي تمرر له الـ Context لا ترتبط دورة حياته بدورة حياة الـ Component الذي مررته. إذا كان كذلك، فاستخدم الـ ApplicationContext.

 

المصادر: 

مصدر 1

كلمات دليلية: android context
9
إعجاب
1595
مشاهدات
0
مشاركة
6
متابع
متميز
محتوى رهيب

التعليقات (0)

لايوجد لديك حساب في عالم البرمجة؟

تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !