SurfaceView وGLSurfaceView

تعتمد واجهة مستخدم إطار عمل تطبيق Android على تسلسل هرمي للكائنات التي تبدأ بـ View . تمر جميع عناصر واجهة المستخدم بسلسلة من القياسات وعملية التخطيط التي تناسبها في منطقة مستطيلة. بعد ذلك، يتم عرض جميع كائنات العرض المرئية على سطح تم إعداده بواسطة 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() فقط بدون surfaceDestroyed() . يظل السطح نشطًا، ويمكن أن يستمر العرض. يمكنك الاستمرار في الحصول على أحداث مصمم الرقصات إذا واصلت طلبها. إذا كانت لديك شاشة قفل تفرض اتجاهًا مختلفًا، فقد تتم إعادة تشغيل نشاطك عندما يكون الجهاز غير فارغ. بخلاف ذلك، يمكنك الخروج من الشاشة فارغة بنفس السطح كما كان من قبل.

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

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

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

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

GLSurfaceView

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

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

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