2011-11-13 15 views
9

देखो, मैं निम्नलिखित कोड है:कैसे हैंडलर पर निर्भर करता है ReceiveResult (परिणाम रिसीवर) लागू किया जाता है?

मेरे कार्रवाई:

final Intent intent = new Intent(getApplicationContext(), MyService.class) 
.putExtra(UploadService.EXTRA_RESULT_RECEIVER, new ResultReceiver(null) { 
      @Override 
      protected void onReceiveResult(int resultCode, Bundle resultData) { 
       super.onReceiveResult(resultCode, resultData); 
       String result = resultData.getString(MyService.EXTRA_RESULT_SUCCESS); 
       ... 
       imageView.setBackgroundDrawable(bitmap);// here my code fails 
      } 
     }) 

MyService:

Bundle b = new Bundle(); 
    b.putString(EXTRA_RESULT_SUCCESS, response.toString()); 
    resultReceiver.send(0, b); 

और अपने आवेदन निम्नलिखित के साथ लाइन पर विफल रहता है "imageView.setBackgroundDrawable (बिटमैप)" अपवाद:

11-13 16:25:38.986: ERROR/AndroidRuntime(3586): FATAL EXCEPTION: IntentService[MyService] 
    android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

लेकिन यह डो जब मैं इस तरह रिसीवर को परिभाषित करता हूं (

new ResultReceiver(new Handler()){.../*here goes the same code as in the first example. nothing has been changed*/} 

तो। जब मैं डिफ़ॉल्ट हैंडलर पास करता हूं तो यह असफल नहीं होता है। और मैं क्यों पूछता हूं? दोनों तरीकों से मेरा कोड लागू किया गया है, लेकिन जब कोई हैंडलर निर्दिष्ट नहीं करता है तो यह विफल हो जाता है। हैंडलर का क्या प्रभाव है?

उत्तर

8

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

+0

मुझे संदेह है। क्या वह परिणाम Reseceiver.onReceiveResult हमेशा गैर-यूआई थ्रेड पर चलाएगा? –

+0

नहीं, यह है कि एक हैंडलर गारंटी का उपयोग करके यह सही धागे पर चलाएगा। आम तौर पर कोई गारंटी नहीं दी जाती है कि रिसीवर को किस धागे पर बुलाया जाएगा। – Femi

+0

समझ गया! यह परिणाम रिसीवर को बुलाए धागे पर आधारित है। त्वरित उत्तर के लिए धन्यवाद। –

3

समस्या यह है क्योंकि imageView.setBackgroundDrawable() को आपकी सेवा के थ्रेड से बुलाया जाता है। यह गलत है। आपको यह सुनिश्चित करना होगा कि यूआई थ्रेड से कोई यूआई अपडेट निष्पादित किया गया हो।

यह स्पष्ट करना मुश्किल है कि आपके द्वारा प्रदान किए गए स्निपेट से क्या बदलना है।

एंड्रॉइड गैर-यूआई धागे को यूआई घटकों (और हैंडलर क्लास विकल्प में से एक) के साथ बातचीत करने की अनुमति देने के लिए कई तकनीकों प्रदान करता है। आईएमएचओ, यदि आप अच्छे एंड्रॉइड एप्लिकेशन विकसित करना चाहते हैं तो यह सही पाने के लिए सबसे महत्वपूर्ण अवधारणा है।

कुछ उपयोगी लिंक्स:

http://developer.android.com/resources/articles/painless-threading.html

What is the Android UiThread (UI thread)

http://www.vogella.de/articles/AndroidPerformance/article.html

+1

हाँ, मुझे लगता है कि समस्या इसलिए होता है क्योंकि यूआई अद्यतन एक और धागे से क्रियान्वित किया जा रहा है। लेकिन ऐसा तब नहीं होता जब मैं एक डिफ़ॉल्ट हैंडलर पास करता हूं। तो जब मैं इसे पास करता हूं, तो क्या यह नया निर्माण करने के बजाय यूआई थ्रेड से सभी चीजें काम करता है? लिंक के लिए धन्यवाद, एक दिलचस्प पढ़ने की तरह लग रहा है! –

0

मेरे लिए निम्नलिखित कार्य करता है। आप "runOnUiThread" विधि का उपयोग कर अपनी यूआई गतिविधि के उसी थ्रेड में बिटमैप अपडेट चला सकते हैं। आप अपने यूआई गतिविधि के भीतरी वर्ग के रूप में निम्नलिखित वर्ग को परिभाषित करना चाहिए:

class UpdateUI implements Runnable 
{ 
    Bitmap newBitmap; 

    public UpdateUI(Bitmap newBitmap) { 
     this.newBitmap = newBitmap; 
    } 
    public void run() { 
     imageView.setBackgroundDrawable(newBitmap); 
    } 
} 

फिर अपने resultReceiver में:

@Override 
protected void onReceiveResult(int resultCode, Bundle resultData) { 
    // after get your bitmap 
    runOnUiThread(new UpdateUI(receivedBitmap)); 
    ... 
} 
संबंधित मुद्दे