SurfaceView और GLSurfaceView

Android ऐप्लिकेशन फ़्रेमवर्क का यूज़र इंटरफ़ेस (यूआई), ऑब्जेक्ट के क्रम पर आधारित होता है. यह क्रम व्यू से शुरू होता है. सभी यूज़र इंटरफ़ेस (यूआई) एलिमेंट को मेज़रमेंट की एक सीरीज़ और लेआउट की प्रोसेस से गुज़रना पड़ता है, ताकि वे रेक्टैंगल आकार वाले एरिया में फ़िट हो सकें. इसके बाद, दिखने वाले सभी व्यू ऑब्जेक्ट को उस प्लैटफ़ॉर्म पर रेंडर किया जाता है जिसे ऐप्लिकेशन को फ़ोरग्राउंड में लाने के दौरान, WindowManager ने सेट अप किया था. ऐप्लिकेशन का यूज़र इंटरफ़ेस (यूआई) थ्रेड, हर फ़्रेम के लिए बफ़र में लेआउट और रेंडरिंग करता है.

SurfaceView

SurfaceView एक ऐसा कॉम्पोनेंट है जिसका इस्तेमाल, अपनी व्यू हैरारकी में एक और कंपोजिट लेयर एम्बेड करने के लिए किया जा सकता है. SurfaceView, दूसरे व्यू के जैसे ही लेआउट पैरामीटर का इस्तेमाल करता है. इसलिए, इसे किसी भी दूसरे व्यू की तरह मैनिप्युलेट किया जा सकता है. हालांकि, SurfaceView का कॉन्टेंट पारदर्शी होता है.

जब किसी बाहरी बफ़र सोर्स, जैसे कि GL कॉन्टेक्स्ट या मीडिया डिकोडर का इस्तेमाल करके रेंडर किया जाता है, तो स्क्रीन पर बफ़र दिखाने के लिए, आपको बफ़र सोर्स से बफ़र कॉपी करने होंगे. SurfaceView का इस्तेमाल करके ऐसा किया जा सकता है.

जब SurfaceView का व्यू कॉम्पोनेंट दिखने वाला होता है, तो फ़्रेमवर्क, SurfaceControl से SurfaceFlinger से नए सर्वफ़ेस का अनुरोध करने के लिए कहता है. जब प्लैटफ़ॉर्म बनाया या नष्ट किया जाता है, तब कॉलबैक पाने के लिए, SurfaceHolder इंटरफ़ेस का इस्तेमाल करें. डिफ़ॉल्ट रूप से, नया प्लैटफ़ॉर्म, ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) प्लैटफ़ॉर्म के पीछे दिखता है. नए प्लैटफ़ॉर्म को सबसे ऊपर रखने के लिए, डिफ़ॉल्ट Z-क्रम को बदला जा सकता है.

SurfaceView की मदद से रेंडर करने की सुविधा तब फ़ायदेमंद होती है, जब आपको किसी अलग प्लैटफ़ॉर्म पर रेंडर करना हो. जैसे, Camera API या OpenGL ES कॉन्टेक्स्ट की मदद से रेंडर करने पर. SurfaceView का इस्तेमाल करके रेंडर करने पर, SurfaceFlinger सीधे स्क्रीन पर बफ़र को कॉम्पोज़ करता है. SurfaceView के बिना, आपको ऑफ़स्क्रीन सरफ़ेस पर बफ़र को कॉम्पोज़ करना होगा. इसके बाद, उन्हें स्क्रीन पर कॉम्पोज़ किया जाता है. इसलिए, SurfaceView की मदद से रेंडर करने पर, अतिरिक्त काम नहीं करना पड़ता. SurfaceView के साथ रेंडर करने के बाद, गतिविधि के लाइफ़साइकल के साथ काम करने के लिए यूज़र इंटरफ़ेस (यूआई) थ्रेड का इस्तेमाल करें. साथ ही, ज़रूरत पड़ने पर व्यू के साइज़ या पोज़िशन में बदलाव करें. इसके बाद, हार्डवेयर कंपोजर, ऐप्लिकेशन के यूज़र इंटरफ़ेस (यूआई) और अन्य लेयर को ब्लेंड करता है.

नया प्लैटफ़ॉर्म, BufferQueue का प्रोड्यूसर साइड है. इसका उपभोक्ता, SurfaceFlinger लेयर है. प्लैटफ़ॉर्म को किसी भी ऐसे तरीके से अपडेट किया जा सकता है जिससे BufferQueue को फ़ीड किया जा सकता है. जैसे, प्लैटफ़ॉर्म से मिलने वाले कैनवस फ़ंक्शन, EGLSurface को अटैच करना, और GLES की मदद से प्लैटफ़ॉर्म पर ड्रॉ करना या प्लैटफ़ॉर्म को लिखने के लिए मीडिया डिकोडर को कॉन्फ़िगर करना.

SurfaceView और गतिविधि पूरी होने की प्रोसेस

SurfaceView का इस्तेमाल करते समय, मुख्य यूज़र इंटरफ़ेस (यूआई) थ्रेड के अलावा किसी दूसरी थ्रेड से, सर्वफ़ेस को रेंडर करें.

SurfaceView वाली गतिविधि के लिए, दो अलग-अलग, लेकिन एक-दूसरे पर निर्भर रहने वाली स्टेट मशीन होती हैं:

  • ऐप्लिकेशन onCreate/onResume/onPause
  • प्लैटफ़ॉर्म बनाया गया/बदला गया/नष्ट किया गया

गतिविधि शुरू होने पर, आपको इस क्रम में कॉलबैक मिलते हैं:

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

'वापस जाएं' पर क्लिक करने पर, आपको ये विकल्प मिलेंगे:

  1. onPause()
  2. surfaceDestroyed() (सर्फ़ेस के हटने से ठीक पहले कॉल किया जाता है)

स्क्रीन को घुमाने पर, गतिविधि को बंद करके फिर से शुरू किया जाता है. इससे आपको पूरा साइकल दिखता है. isFinishing() को चुनकर, यह पता लगाया जा सकता है कि यह तुरंत रीस्टार्ट है या नहीं. किसी गतिविधि को इतनी तेज़ी से शुरू/बंद किया जा सकता है कि surfaceCreated(), onPause() के बाद शुरू हो जाए.

स्क्रीन को ब्लैक करने के लिए पावर बटन पर टैप करने पर, आपको surfaceDestroyed() के बिना सिर्फ़ onPause() दिखता है. प्लैटफ़ॉर्म चालू रहता है और रेंडरिंग जारी रहती है. अगर आपने कोरियोग्राफ़र इवेंट के लिए अनुरोध किया है, तो आपको ये इवेंट मिलते रहेंगे. अगर आपके डिवाइस पर ऐसी लॉक स्क्रीन है जो डिवाइस के ओरिएंटेशन को बदल देती है, तो डिवाइस को अनब्लॉक करने पर आपकी गतिविधि फिर से शुरू हो सकती है. इसके अलावा, स्क्रीन ब्लैंक मोड से बाहर निकलने के लिए, पहले की तरह ही किसी भी स्क्रीन का इस्तेमाल किया जा सकता है.

थ्रेड के दिखने की अवधि को, स्क्रीन या गतिविधि से जोड़ा जा सकता है. यह इस बात पर निर्भर करता है कि स्क्रीन खाली होने पर आपको क्या करना है. थ्रेड, गतिविधि शुरू/बंद होने पर या प्लैटफ़ॉर्म बनाने/नष्ट करने पर शुरू/बंद हो सकती है.

गतिविधि शुरू/बंद होने पर थ्रेड शुरू/बंद होने की सुविधा, ऐप्लिकेशन के लाइफ़साइकल के साथ अच्छी तरह से काम करती है. आपने onResume() में रेंडरर थ्रेड शुरू किया और onStop() में उसे बंद किया. थ्रेड बनाते और कॉन्फ़िगर करते समय, कभी-कभी ऐसा होता है कि प्लैटफ़ॉर्म पहले से मौजूद होता है और कभी-कभी ऐसा नहीं होता. उदाहरण के लिए, पावर बटन से स्क्रीन को टॉगल करने के बाद भी, वह प्लैटफ़ॉर्म चालू रहता है. थ्रेड में शुरू करने से पहले, आपको प्लैटफ़ॉर्म बनने का इंतज़ार करना होगा. surfaceCreate() कॉलबैक में शुरू नहीं किया जा सकता, क्योंकि अगर प्लैटफ़ॉर्म फिर से नहीं बनाया गया है, तो यह फिर से ट्रिगर नहीं होगा. इसके बजाय, सरफ़ेस की स्थिति के बारे में क्वेरी करें या उसे कैश मेमोरी में सेव करें और उसे रेंडरर थ्रेड पर भेजें.

थ्रेड को, सर्वर पर पेज बनाने/नष्ट करने के साथ शुरू या बंद करने की सुविधा अच्छी तरह से काम करती है, क्योंकि सर्वर और रेंडरर एक-दूसरे से लॉजिक के हिसाब से जुड़े होते हैं. आपने प्लैटफ़ॉर्म बनाने के बाद थ्रेड शुरू की है. इससे, एक थ्रेड से दूसरी थ्रेड में होने वाले कम्यूनिकेशन से जुड़ी कुछ समस्याओं से बचा जा सकता है. साथ ही, प्लैटफ़ॉर्म पर बनाए गए/बदले गए मैसेज को आसानी से फ़ॉरवर्ड किया जा सकता है. यह पक्का करने के लिए कि स्क्रीन के खाली होने पर रेंडरिंग रुक जाए और खाली न होने पर फिर से शुरू हो जाए, Choreographer को फ़्रेम ड्रॉ कॉलबैक को ट्रिगर करने से रोकें. onResume(), रेंडरर थ्रेड के चलने पर कॉलबैक फिर से शुरू करता है. हालांकि, अगर फ़्रेम के बीच बीते समय के आधार पर ऐनिमेशन बनाया जाता है, तो अगले इवेंट के आने से पहले काफ़ी समय लग सकता है. इस समस्या को ठीक करने के लिए, 'रोकें/फिर से शुरू करें' मैसेज का इस्तेमाल करें.

दोनों विकल्पों में, रेंडरर थ्रेड को कॉन्फ़िगर करने के तरीके और उसके चलने पर फ़ोकस किया जाता है. भले ही, थ्रेड की लाइफ़स्पैन, गतिविधि या प्लैटफ़ॉर्म से जुड़ी हो. इससे जुड़ी एक समस्या यह है कि onStop() या onSaveInstanceState() में गतिविधि बंद होने पर, थ्रेड से स्थिति कैसे निकाली जाए. ऐसे मामलों में, थ्रेड के लाइफ़स्पैन को गतिविधि से जोड़ना सबसे अच्छा काम करता है. ऐसा इसलिए, क्योंकि रेंडरर थ्रेड में शामिल होने के बाद, रेंडर किए गए थ्रेड की स्थिति को सिंक्रोनाइज़ेशन प्राइमिटिव के बिना ऐक्सेस किया जा सकता है.

GLSurfaceView

GLSurfaceView क्लास, EGL कॉन्टेक्स्ट, इंटरथ्रेड कम्यूनिकेशन, और ऐक्टिविटी लाइफ़साइकल के साथ इंटरैक्शन को मैनेज करने के लिए, हेल्पर क्लास उपलब्ध कराती है. GLES का इस्तेमाल करने के लिए, आपको GLSurfaceView का इस्तेमाल करने की ज़रूरत नहीं है.

उदाहरण के लिए, GLSurfaceView रेंडरिंग के लिए एक थ्रेड बनाता है और वहां एक EGL कॉन्टेक्स्ट कॉन्फ़िगर करता है. गतिविधि के रुकने पर, स्टेटस अपने-आप हट जाता है. ज़्यादातर ऐप्लिकेशन को GLSurfaceView के साथ GLES का इस्तेमाल करने के लिए, EGL के बारे में कुछ भी जानने की ज़रूरत नहीं होती.

ज़्यादातर मामलों में, GLSurfaceView की मदद से GLES के साथ काम करना आसान हो जाता है. कुछ मामलों में, यह समस्या पैदा कर सकता है.