2012-04-28 10 views
8

पर मेरे पास एक SurfaceView एक्सटेंशन है जहां इसकी नंगे हड्डियों को Lunar Lander उदाहरण में लागू किया गया है। यही कारण है, ड्राइंग Thread की run() विधि अनिवार्य है:सतह दृश्य में थ्रेड रोकने के बावजूद SurfaceView थ्रेड में शून्य कैनवास, (केवल एंड्रॉइड 4/आईसीएस

public void run() { 
    while (mRun) { 
     Canvas c; 
      try { 
       c = mSurfaceHolder.lockCanvas(); 
       synchronized (mSurfaceHolder) { 
        doDraw(c); // Main drawing method - not included in this code snippet 
       }         
      } 

      finally { 
       // do this in a finally so that if an exception is thrown 
       // during the above, we don't leave the Surface in an 
       // inconsistent state 
       if (c != null) { 
        mSurfaceHolder.unlockCanvasAndPost(c); 
       } 
      } 
     } 
    } 
} 

और Thread ठीक से जब सतह नष्ट हो जाता है बंद कर दिया जाता है:

public void surfaceDestroyed(SurfaceHolder holder) { 
    // we have to tell thread to shut down & wait for it to finish, or else 
    // it might touch the Surface after we return and explode 
    boolean retry = true; 
    thread.setRunning(false); 
    while (retry) { 
     try { 
      thread.join(); 
      retry = false; 
     } 
     catch (InterruptedException e) { 
     } 
    } 
} 

उपकरणों मैं आमतौर पर तारीख करने के लिए पर परीक्षण किया है पर (HTC इच्छा, इच्छा एचडी, और आर्कोस 101 जो उनके बीच ओएस 2.2 और 2.3.3 है यदि मुझे सही याद है) उपरोक्त के साथ कोई समस्या नहीं हुई है। यही है, जब सतह नष्ट हो जाती है क्योंकि उपयोगकर्ता Activity या Activity से बाहर निकलता है, तो surfaceDestroyed() के भीतर कोड हमेशा यह सुनिश्चित करता है कि mSurfaceHolder.lockCanvas() को null वापस करने के लिए कभी भी बुलाया नहीं जाएगा।

अंतर मैं अपने नए HTC एक एक्स पर मिल गया है जो एंड्रॉयड चल रहा है 4/आईसीएस, तथापि, है कि विधि surfaceDestroyed() (यानी कि विधि के भीतर कोड अभी भी निष्पादित किया जाता है) मेरी ड्राइंग के लिए कॉल के दौरान Thread दी जाएगी से null कैनवास। यह निश्चित रूप से एक आवेदन दुर्घटना का कारण बन जाएगा। मेरी एक एक्स पर, यह हर एक बार सतह नष्ट हो जाता है क्या होगा - चाहे वह फोन घूर्णन, Activity से बाहर समर्थन की वजह से हो, आदि

क्योंकि मैं के तहत किया गया है कि मैं इस बारे में उलझन में हूँ इंप्रेशन कि mSurfaceHolder.lockCanvas() को एक गैर-nullCanvassurfaceDestroyed() तक वास्तव में से बाहर निकलना चाहिए। दरअसल, यह है कि क्या जावाडोक कहते है:

This is called immediately before a surface is being destroyed. After returning from this call, you should no longer try to access this surface. If you have a rendering thread that directly accesses the surface, you must ensure that thread is no longer touching the Surface before returning from this function.

अब के लिए मेरे समाधान सिर्फ null के लिए जाँच करने के लिए है। यह ठीक काम करता है:

if(c != null){ 
    doDraw(c); // Main drawing method - not included in this code snippet 
} 

लेकिन, कोई विचार है कि मुझे अचानक एंड्रॉइड 4/आईसीएस के लिए ऐसा क्यों करना है?

+0

रिटर्निंग 'नल' आपको सतह को छूने से रोकने का एक तरीका है, इसलिए आप जो भी करते हैं वह ठीक होना चाहिए। हालांकि अंतर्निहित कार्यान्वयन में क्यों या क्या बदला गया। – zapl

+0

धन्यवाद, zapl। हाँ, यह वास्तव में विचित्र है। जब तक कि कुछ अजीब बात न हो, मैं कार्यान्वयन में इस स्पष्ट परिवर्तन के कारण कर रहा हूं, निश्चित रूप से सतह के दृश्य-आधारित ऐप्स बहुत सारे आईसीएस पर मरने जा रहे हैं। – Trevor

+0

क्या किसी को "आधिकारिक" पता चलता है क्योंकि मुझे यह त्रुटि आईसीएस डिवाइस या अनुकरणकर्ताओं पर भी मिली है। – Lenciel

उत्तर

5

बस मेरी टिप्पणी पर विस्तृत करने के लिए, ऐसा लगता है कि व्यवहार में इस बदलाव के लिए एक बग टिकट खुला है, जिसे आप यहां पा सकते हैं: http://code.google.com/p/android/issues/detail?id=38658। यदि यह आपको प्रभावित करता है, तो यह शायद इसे देखकर लायक हो सकता है, बस यह थोड़ा महत्व बढ़ाता है!

व्यक्तिगत रूप से, मैंने इसे हाल ही में देखा है, चंद्र लैंडर उदाहरण का उपयोग करके जो नवीनतम एंड्रॉइड एसडीके के साथ आता है। मैंने इसे अपने एचटीसी सेंसेशन एक्सई (4.0.3) और अभिविन्यास परिवर्तन पर रखा है, सतह को नष्ट होने से पहले मुझे कुछ नल कैनवास लौटाए जा रहे हैं।

तो मैं जिस कामकाज का उपयोग करता हूं वह सिर्फ दो बार जांचने के लिए है कि कैनवास इसे मेरे अपडेट में पास करने से पहले शून्य नहीं है और विधियों को प्रस्तुत करता है।

एंडी

+0

दिलचस्प! मुझे यह समस्या भी थी, और इसी तरह से इसके आसपास मिल गया, एकमात्र अलग यह है कि मैंने अपनी ड्रॉ विधि के अंदर वास्तव में शून्य कैनवास के लिए अपनी जांच डाली :-) – Zippy

+0

बस दिनों के लिए एक ही समस्या के साथ संघर्ष करने के बाद यह पाया! आपका बहुत बहुत धन्यवाद! मैंने शून्य की जांच करने के बारे में सोचा था, लेकिन मैं एक और समाधान की तलाश में रहा क्योंकि यह शून्य के लिए जांच करने के लिए गन्दा लगता है, लेकिन मुझे लगता है कि हमें इसे इस तरह करना है। –

0

मैं छोटा सा प्रयोग कर दिया। मैं इस तरह surfaceDestroyed() विधि में कुछ अधिसूचना झंडे डाल:

public void surfaceDestroyed(SurfaceHolder holder) { 
Log.i("i","i have started"); 
...[the code]... 
Log.i("i","i have finished"); 
} 

मुझे क्या पता चला है, तथ्य यह है कि nullPionterExceptionOccurs पहले ध्वज के बाद होता है है, लेकिन दूसरा एक से पहले।आपके प्रश्न के लिए सबसे संभावित उत्तरकर्ता यह है कि जब आप पुराना दृश्य पहुंच योग्य होते हैं तो आप कैनवास को लॉक करते हैं, आप इसे आकर्षित करते हैं लेकिन इस बीच स्क्रीन बदल जाती है। तो जब कैनवास अनलॉक करते हैं तो परिणाम दिखाने के लिए कोई जगह नहीं है- त्रुटि उत्पन्न होती है।

पीएस नमूना एंड्रॉइड कोड से चंद्र लैंडर के साथ थोड़ा सा खेलें और गेम काम करते समय स्क्रीन को घुमाने की कोशिश करें। जब त्रुटि उत्पन्न होगी तो देखें कि बैकग्राउंड बिटमैप कैसे खींचा जा रहा था। आपको पता चलेगा कि स्क्रीन अभिविन्यास बदल गया है, लेकिन कार्यक्रम ने बिटमैप को आकर्षित करने का प्रयास किया जैसे कि कुछ भी खुश नहीं है।

संबंधित मुद्दे