تستند واجهة مستخدم إطار عمل تطبيقات Android إلى تسلسل هرمي للكائنات يبدأ بـ View. تخضع جميع عناصر واجهة المستخدم لسلسلة من القياسات وعملية التنسيق التي تضعها في مساحة مستطيلة. بعد ذلك، يعرض إطار العمل جميع عناصر العرض المرئية على مساحة تم إعدادها بواسطة WindowManager عندما تم وضع التطبيق في المقدّمة. ينفّذ سلسلة التعليمات الخاصة بواجهة المستخدم في التطبيق عملية التخطيط والعرض في المخزن المؤقت لكل إطار.
SurfaceView
SurfaceView هو مكوّن يمكنك استخدامه لتضمين طبقة مركّبة إضافية ضمن بنية العرض. تتلقّى SurfaceView معلَمات التنسيق نفسها التي تتلقّاها طرق العرض الأخرى، لذا يمكن التلاعب بها مثل أي طريقة عرض أخرى، ولكن محتوى SurfaceView يكون شفافًا.
عند العرض باستخدام مصدر مخزن مؤقت خارجي، مثل سياق GL أو برنامج ترميز وسائط، عليك نسخ المخازن المؤقتة من مصدر المخزن المؤقت لعرضها على الشاشة. يمكنك إجراء ذلك باستخدام SurfaceView.
عندما يكون مكوّن العرض الخاص بـ SurfaceView على وشك أن يصبح مرئيًا، يطلب إطار العمل من SurfaceControl طلب سطح جديد من SurfaceFlinger. لتلقّي عمليات ردّ الاتصال عند إنشاء أو إيقاف السطح، استخدِم واجهة SurfaceHolder. بشكلٍ تلقائي، يضع إطار العمل السطح الذي تم إنشاؤه حديثًا خلف سطح واجهة مستخدم التطبيق. يمكنك إلغاء ترتيب Z التلقائي لوضع السطح الجديد في الأعلى.
يكون العرض باستخدام SurfaceView مفيدًا في الحالات التي تحتاج فيها إلى العرض على مساحة عرض منفصلة، مثل العرض باستخدام Camera API أو سياق OpenGL ES. عند العرض باستخدام SurfaceView، يركّب SurfaceFlinger المخازن المؤقتة مباشرةً على الشاشة. بدون SurfaceView، عليك دمج المخازن المؤقتة في مساحة عرض خارج الشاشة، ثم دمجها مع الشاشة، لذا فإنّ العرض باستخدام SurfaceView يوفّر عليك هذا العمل الإضافي. بعد العرض باستخدام SurfaceView، استخدِم سلسلة محادثات واجهة المستخدم للتنسيق مع مراحل نشاط التطبيق وإجراء تعديلات على حجم العرض أو موضعه إذا لزم الأمر. بعد ذلك، يدمج Hardware Composer واجهة مستخدم التطبيق مع الطبقات الأخرى.
السطح الجديد هو جانب المنتج في BufferQueue، ومستهلكه هو طبقة SurfaceFlinger. يمكنك تعديل مساحة العرض باستخدام أي آلية يمكنها توفير بيانات إلى BufferQueue، مثل وظائف Canvas التي توفّرها مساحة العرض، أو ربط EGLSurface والرسم على مساحة العرض باستخدام GLES، أو ضبط برنامج ترميز الوسائط لكتابة مساحة العرض.
SurfaceView ودورة حياة النشاط
عند استخدام SurfaceView، يجب عرض السطح من سلسلة محادثات أخرى غير سلسلة محادثات واجهة المستخدم الرئيسية.
بالنسبة إلى نشاط يتضمّن SurfaceView، هناك آلتان منفصلتان للحالات ولكنهما تعتمدان على بعضهما البعض:
- التطبيق
onCreate
/onResume
/onPause
- تم إنشاء/تغيير/إزالة السطح
عند بدء النشاط، ستتلقّى عمليات ردّ الاتصال بهذا الترتيب:
onCreate()
onResume()
surfaceCreated()
surfaceChanged()
إذا نقرت على "رجوع"، سيظهر لك ما يلي:
onPause()
-
surfaceDestroyed()
(يتم استدعاؤها قبل إغلاق السطح مباشرةً)
إذا أدرت الشاشة، سيتم إيقاف النشاط وإعادة إنشائه، وستحصل على الدورة الكاملة. يمكنك معرفة ما إذا كانت إعادة التشغيل سريعة من خلال التحقّق من isFinishing()
. من المحتمل أن يتم بدء نشاط أو إيقافه بسرعة كبيرة
بحيث يحدث surfaceCreated()
بعد onPause()
.
إذا نقرت على زر التشغيل لإفراغ الشاشة، سيظهر لك onPause()
فقط بدون surfaceDestroyed()
. يظل السطح نشطًا، ويمكن أن يستمر العرض. يمكنك مواصلة تلقّي أحداث Choreographer إذا واصلت طلبها. إذا كانت لديك شاشة قفل تفرض اتجاهًا مختلفًا، قد تتم إعادة تشغيل نشاطك عند إزالة شاشة التوقف. بخلاف ذلك، يمكنك الخروج من وضع الشاشة الفارغة مع
السطح نفسه كما كان من قبل.
يمكن ربط مدة بقاء سلسلة المحادثات بالسطح أو بالنشاط، استنادًا إلى ما تريد حدوثه عند إطفاء الشاشة. يمكن بدء سلسلة المحادثات أو إيقافها إما عند بدء النشاط أو إيقافه، أو عند إنشاء السطح أو إتلافه.
ويؤدي بدء سلسلة المحادثات وإيقافها عند بدء النشاط وإيقافه إلى توافق جيد مع دورة حياة التطبيق. يمكنك بدء سلسلة معالجة العرض في onResume()
وإيقافها في onStop()
. عند إنشاء سلسلة المحادثات وإعدادها، قد تكون مساحة العرض متوفّرة في بعض الأحيان، وغير متوفّرة في أحيان أخرى (على سبيل المثال، تظل نشطة بعد إيقاف الشاشة وتشغيلها باستخدام زر التشغيل). عليك الانتظار إلى أن يتم إنشاء السطح قبل بدء عملية التهيئة في سلسلة التعليمات. لا يمكنك
بدء عملية التهيئة في دالة معاودة الاتصال surfaceCreate()
لأنّها لن يتم تشغيلها
مجددًا إذا لم تتم إعادة إنشاء مساحة العرض. بدلاً من ذلك، يمكنك طلب حالة Surface أو تخزينها مؤقتًا، ثم إعادة توجيهها إلى سلسلة عرض العناصر.
ويكون بدء سلسلة التعليمات وإيقافها عند إنشاء السطح أو إتلافه أمرًا مناسبًا لأنّ السطح والعارض مرتبطان منطقيًا. تبدأ سلسلة المحادثات بعد إنشاء السطح، ما يجنّبك بعض المشاكل المتعلّقة بالتواصل بين سلاسل المحادثات، ويتم إعادة توجيه الرسائل التي تم إنشاؤها أو تغييرها على السطح. للتحقّق من توقّف العرض عند إفراغ الشاشة واستئنافه عند إعادة ملئها، اطلب من Choreographer إيقاف استدعاء دالة معاودة الاتصال الخاصة برسم الإطار. onResume()
يستأنف عمليات معاودة الاتصال إذا كان مؤشر ترابط العرض قيد التشغيل. ومع ذلك، إذا كنت تحرّك العناصر استنادًا إلى الوقت المنقضي بين اللقطات، قد تحدث فجوة كبيرة قبل وصول الحدث التالي، ويمكن حلّ هذه المشكلة باستخدام رسالة إيقاف مؤقت/استئناف صريحة.
يركّز كلا الخيارين، سواء كانت مدة بقاء سلسلة المحادثات مرتبطة بنشاط أو بواجهة، على كيفية ضبط سلسلة محادثات العرض وما إذا كانت قيد التنفيذ. من المشاكل ذات الصلة استخراج الحالة من سلسلة التعليمات البرمجية عند إيقاف النشاط (في onStop()
أو onSaveInstanceState()
). في مثل هذه الحالات، يكون ربط مدة سلسلة التعليمات البرمجية بمدة النشاط هو الأفضل، لأنّه بعد ربط سلسلة التعليمات البرمجية الخاصة بعرض المحتوى، يمكن الوصول إلى حالة سلسلة التعليمات البرمجية المعروضة بدون عناصر مزامنة.
GLSurfaceView
يوفر صف GLSurfaceView صفوفًا مساعدة لإدارة سياقات EGL، والتواصل بين سلاسل المحادثات، والتفاعل مع دورة حياة النشاط. لست بحاجة إلى استخدام GLSurfaceView لاستخدام GLES.
على سبيل المثال، تنشئ GLSurfaceView سلسلة محادثات للعرض وتضبط سياق EGL فيها. يتم تنظيف الحالة تلقائيًا عند إيقاف النشاط مؤقتًا. لا تحتاج معظم التطبيقات إلى معرفة أي شيء عن EGL لاستخدام GLES مع GLSurfaceView.
في معظم الحالات، يمكن أن تسهّل GLSurfaceView عملية استخدام GLES. وفي بعض الحالات، قد يعيق ذلك عملية التعلّم.