SurfaceView و GLSurfaceView

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

عرض السطح

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

عند التقديم باستخدام مصدر مخزن مؤقت خارجي ، مثل سياق GL أو وحدة فك ترميز الوسائط ، تحتاج إلى نسخ المخازن المؤقتة من مصدر المخزن المؤقت لعرض المخازن المؤقتة على الشاشة. يتيح لك استخدام SurfaceView القيام بذلك.

عندما يكون مكون عرض SurfaceView على وشك الظهور ، يطلب إطار العمل من SurfaceControl طلب سطح جديد من SurfaceFlinger. لتلقي عمليات رد النداء عند إنشاء السطح أو إتلافه ، استخدم واجهة SurfaceHolder . بشكل افتراضي ، يتم وضع السطح الذي تم إنشاؤه حديثًا خلف سطح واجهة مستخدم التطبيق. يمكنك تجاوز ترتيب Z الافتراضي لوضع السطح الجديد في المقدمة.

يعد التقديم باستخدام SurfaceView مفيدًا في الحالات التي تحتاج فيها إلى العرض على سطح منفصل ، مثل عند العرض باستخدام Camera API أو سياق OpenGL ES. عندما تقوم بالتقديم باستخدام SurfaceView ، يقوم SurfaceFlinger بإنشاء مخازن مؤقتة مباشرة على الشاشة. بدون SurfaceView ، تحتاج إلى تركيب المخازن المؤقتة على سطح خارج الشاشة ، والذي يتم بعد ذلك تركيبه على الشاشة ، لذا فإن العرض باستخدام SurfaceView يلغي العمل الإضافي. بعد التقديم باستخدام SurfaceView ، استخدم مؤشر ترابط واجهة المستخدم للتنسيق مع دورة حياة النشاط وإجراء تعديلات على حجم أو موضع العرض إذا لزم الأمر. بعد ذلك ، يقوم مؤلف الأجهزة بمزج واجهة مستخدم التطبيق والطبقات الأخرى.

السطح الجديد هو جانب المنتج من BufferQueue ، والذي يكون مستهلكه عبارة عن طبقة SurfaceFlinger. يمكنك تحديث السطح بأي آلية يمكنها تغذية BufferQueue ، مثل وظائف Canvas المزودة بالسطح ، وإرفاق سطح EGLSurface والرسم على السطح باستخدام GLES ، أو تكوين وحدة فك ترميز الوسائط لكتابة السطح.

SurfaceView ودورة حياة النشاط

عند استخدام SurfaceView ، قم بعرض السطح من مؤشر ترابط بخلاف مؤشر ترابط واجهة المستخدم الرئيسي.

بالنسبة للنشاط باستخدام SurfaceView ، هناك جهازان منفصلان ولكن مترابطان:

  • التطبيق onCreate / onResume / onPause
  • تم إنشاء السطح / تغييره / إتلافه

عندما يبدأ النشاط ، ستحصل على عمليات استرجاع بالترتيب التالي:

  1. onCreate()
  2. onResume()
  3. surfaceCreated()
  4. surfaceChanged()

إذا نقرت مرة أخرى ، فستحصل على:

  1. onPause()
  2. surfaceDestroyed() (يسمى قبل أن يختفي السطح مباشرة)

إذا قمت بتدوير الشاشة ، فسيتم هدم النشاط وإعادة إنشائه وستحصل على الدورة الكاملة. يمكنك معرفة أنها إعادة تشغيل سريعة عن طريق التحقق من isFinishing() . فمن الممكن لبدء / إيقاف النشاط بسرعة بحيث surfaceCreated() يحدث بعد onPause() .

إذا قمت بالنقر فوق زر الطاقة onPause() الشاشة ، فستحصل فقط على onPause() بدون surfaceDestroyed() . يظل السطح نشطًا ، ويمكن أن يستمر العرض. يمكنك الحصول على أحداث مصمم الرقص باستمرار إذا واصلت طلبها. إذا كانت لديك شاشة قفل تفرض اتجاهًا مختلفًا ، فقد تتم إعادة تشغيل نشاطك عندما يكون الجهاز غير معطل. خلاف ذلك ، يمكنك الخروج من الشاشة فارغة بنفس السطح كما كان من قبل.

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

إن بدء / إيقاف الموضوع في بدء / إيقاف النشاط يعمل بشكل جيد مع دورة حياة التطبيق. تبدأ سلسلة العارض في onResume() onStop() في onStop() . عند إنشاء الخيط وتكوينه ، أحيانًا يكون السطح موجودًا بالفعل ، وفي أحيان أخرى لا يكون (على سبيل المثال ، لا يزال نشطًا بعد تبديل الشاشة باستخدام زر الطاقة). عليك الانتظار حتى يتم إنشاء السطح قبل التهيئة في الخيط. لا يمكنك التهيئة في surfaceCreate() callback لأنه لن يتم surfaceCreate() مرة أخرى إذا لم يتم إعادة إنشاء السطح. بدلاً من ذلك ، يمكنك الاستعلام عن حالة السطح أو تخزينها مؤقتًا ، وإعادة توجيهها إلى مؤشر ترابط العارض.

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

يركز كلا الخيارين ، سواء كان عمر الخيط مرتبطًا بالنشاط أو السطح ، على كيفية تكوين مؤشر ترابط العارض وما إذا كان يتم تنفيذه. أحد المخاوف ذات الصلة هو استخراج الحالة من الخيط عند onStop() النشاط (في onStop() أو onSaveInstanceState() ) ؛ في مثل هذه الحالات ، يعمل ربط عمر مؤشر الترابط بالنشاط بشكل أفضل لأنه بعد انضمام مؤشر ترابط جهاز العرض ، يمكن الوصول إلى حالة مؤشر الترابط الذي تم تقديمه بدون أساسيات المزامنة.

GLSurfaceView

توفر فئة GLSurfaceView فئات مساعدة لإدارة سياقات EGL والتواصل بين الخيوط والتفاعل مع دورة حياة النشاط. لا تحتاج إلى استخدام GLSurfaceView لاستخدام GLES.

على سبيل المثال ، يقوم GLSurfaceView بإنشاء مؤشر ترابط لتقديم وتكوين سياق EGL هناك. يتم تنظيف الحالة تلقائيًا عند توقف النشاط مؤقتًا. لا تحتاج معظم التطبيقات إلى معرفة أي شيء عن EGL لاستخدام GLES مع GLSurfaceView.

في معظم الحالات ، يمكن أن يجعل GLSurfaceView العمل مع GLES أسهل. في بعض الحالات ، يمكن أن يعيق الطريق.