क्या ब्रॉडकास्टसीवर.ऑनर्सिव हमेशा यूआई थ्रेड में चलता है?


117

मेरे ऐप में, मैं एक कस्टम बनाता हूं BroadcastReceiverऔर इसे अपने संदर्भ में मैन्युअल रूप से पंजीकृत करता हूं Context.registerReceiver। मेरे पास एक AsyncTaskऐसा प्रेषण है जो नोटिफ़ायर-इंटेंट्स के माध्यम से भेजता है Context.sendBroadcast। इरादा एक गैर-यूआई कार्यकर्ता थ्रेड से भेजा जाता है, लेकिन ऐसा लगता है कि BroadcastReceiver.onReceive(जो कहा जाता है कि इंटेंट्स) हमेशा यूआई थ्रेड (जो मेरे लिए अच्छा है) में चलता है। क्या यह गारंटी है या मुझे उस पर भरोसा नहीं करना चाहिए?

जवाबों:


163

क्या ब्रॉडकास्टसीवर.ऑनर्सिव हमेशा यूआई थ्रेड में चलता है?

हाँ।


9
क्या यह कहीं दस्तावेज है?
हेंस स्ट्रू

15
@hannes: 99.44% समय, अगर एंड्रॉइड आपके कोड को कॉल कर रहा है, तो यह मुख्य एप्लिकेशन थ्रेड पर है। सभी जीवन चक्र के तरीकों (जैसे, onCreate(), onReceive()) मुख्य आवेदन धागे पर कहा जाता है। और, इसके लिए डॉक्स में प्रलेखित किया गया है onReceive(): goo.gl/8kPuH
CommonsWare

2
ठीक है, मैं सिर्फ "हमेशा" के रूप में डॉक्स से "मुख्य रूप से थ्रेड के भीतर बुलाया जाता है" की व्याख्या कर रहा हूं और आशा है कि चीजें नहीं टूटेंगी ;-) धन्यवाद
हेंस स्ट्रू

4
@ हैन्स स्ट्रू: मुझे नहीं पता कि उन्होंने अपनी भाषा को "सामान्य रूप से" क्यों सुनाया। मैं किसी भी मामले के बारे में नहीं सोच सकता, जहां onReceive()मुख्य एप्लिकेशन ("यूआई") थ्रेड के अलावा थ्रेड पर कॉल किया जाता है।
कॉमन्सवेयर 16

31
@CommonsWare: "मैं किसी भी मामले के बारे में नहीं सोच सकता, जहां onReceive () को मुख्य एप्लिकेशन (" UI ") थ्रेड के अलावा किसी थ्रेड पर कॉल किया जाता है - यह मामला है यदि ब्रॉडकास्टसीवर का उपयोग रजिस्टरराइवर (ब्रॉडकास्टसीवर, इंटेंटफिल्टर, स्ट्रिंग) का उपयोग करके किया जाता है। हैंडलर), हैंडलर तर्क शून्य नहीं है, और मुख्य एप्लिकेशन थ्रेड के अलावा किसी थ्रेड में बनाए गए हैंडलर को संदर्भित करता है।
जूल्स

76

चूंकि आप रिसीवर को गतिशील रूप से पंजीकृत करते हैं, इसलिए आप निर्दिष्ट कर सकते हैं कि एक और धागा (UI थ्रेड के अलावा) संभालता है onReceive()। यह RegisterReceiver () के हैंडलर पैरामीटर के माध्यम से किया जाता है ।

उस ने कहा, यदि आपने एक और हैंडलर निर्दिष्ट नहीं किया, तो यह हमेशा यूआई थ्रेड पर संभाला जाएगा।


हाँ। हैंडलर पैरामीटर के माध्यम से इसे बदलने की आपकी क्षमता की तरह लगता है कि उन्होंने डॉक्स में अपनी भाषा को "हेज" क्यों किया है।
एंड्रयू मैकेंजी

64

क्या ब्रॉडकास्टसीवर.ऑनर्सिव हमेशा यूआई थ्रेड में चलता है?

आमतौर पर, यह सब निर्भर करता है कि आप इसे कैसे पंजीकृत करते हैं।

यदि आप अपना BroadcastReceiverउपयोग पंजीकृत करते हैं:

registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

यह मुख्य गतिविधि थ्रेड (उर्फ यूआई थ्रेड) में चलेगा ।

यदि आप किसी भिन्न थ्रेड परBroadcastReceiver मान्य Handler रनिंग का उपयोग कर अपना पंजीकरण करते हैं :

registerReceiver (BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)

यह आपके संदर्भ में चलेगा Handler

उदाहरण के लिए:

HandlerThread handlerThread = new HandlerThread("ht");
handlerThread.start();
Looper looper = handlerThread.getLooper();
Handler handler = new Handler(looper);
context.registerReceiver(receiver, filter, null, handler); // Will not run on main thread

विवरण यहाँ और यहाँ


3
थोड़ी देर के लिए इस विकल्प को देखने के बाद, मुझे अंततः पता चला कि लोकलब्रॉडकास्टमैन एक कस्टम हैंडलर का उपयोग करने का समर्थन नहीं करता है। इसलिए यदि आप अपने रिसीवर को पंजीकृत करने के लिए एक संदर्भ के बजाय एक एलबीएम का उपयोग कर रहे हैं, तो यह दृष्टिकोण लागू नहीं होता है। दुर्भाग्य से, उस स्थिति में ऐसा लगता है कि हमारा एकमात्र विकल्प बचा है पृष्ठभूमि पर पाने के लिए और 10 ए निष्क्रियता के बाद ट्रिगर करने वाले एएनआर से बचने के लिए एक सेवा का उपयोग करना है।
गमले

9

जैसा कि पिछले उत्तर सही ढंग से कहा onReceiveगया है, यह उस धागे पर चलेगा, जिसके साथ पंजीकृत है अगर उस स्वाद को registerReceiver()एक हैंडलर स्वीकार करता है - अन्यथा मुख्य धागे पर।

सिवाय इसके कि यदि रिसीवर पंजीकृत है LocalBroadcastManagerऔर प्रसारण के माध्यम से sendBroadcastSync- जहां यह जाहिरा तौर पर उस थ्रेड पर चलेगा जो कॉल करता हैsendBroadcastSync.


मैं भाग से सहमत नहीं हूं and the broadcast is via sendBroadcastSync। जब हम LocalBroadcastManagerरिसीवर को पंजीकृत करने के लिए उपयोग करते हैं , तो इसे मुख्य थ्रेड द्वारा बुलाया जाना चाहिए चाहे उपयोग करें sendBroadcastSyncया sendBroadcast। तो कुंजी यह है कि LocalBroadcastManagerरजिस्टर करने के लिए उपयोग करना। क्या मैं सही हू?
किडोहेर

@kidoher: क्या आपने यहां कोड लिंक का अनुसरण किया है: stackoverflow.com/q/20820244/281545 ?
Mr_and_Mrs_D

0

YES Context.registerReceiver (ब्रॉडकास्ट रिसिवर रिसीवर, इंटेंटफिल्टर फ़िल्टर, स्ट्रिंग ब्रॉडकास्टरमिशन, हैंडलर शेड्यूलर)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.