हैंडलर बनाम AsyncTask बनाम थ्रेड [बंद]


382

मैं थोड़ा अंतर के बारे में उलझन में मिल गया Handlers, AsyncTaskऔर Threadsएंड्रॉयड में। मैंने स्टैकऑवरफ्लो में यहाँ कुछ ब्लॉग और प्रश्न पढ़े हैं।

Handlerपृष्ठभूमि धागे हैं जो आपको UI के साथ संवाद करने के लिए प्रदान करते हैं। उदाहरण के लिए, एक प्रगति पट्टी को अपडेट करना Handler। हैंडलर का उपयोग करने से आपको फायदा होता है MessagingQueues, इसलिए यदि आप संदेशों को शेड्यूल करना चाहते हैं या कई यूआई तत्वों को अपडेट करना चाहते हैं या दोहराए गए कार्य करना चाहते हैं।

AsyncTaskसमान हैं, वास्तव में, वे उपयोग करते हैं Handler, लेकिन UI थ्रेड में नहीं चलता है, इसलिए यह डेटा लाने के लिए अच्छा है, उदाहरण के लिए वेब सेवाएं प्राप्त करना। बाद में आप यूआई के साथ बातचीत कर सकते हैं।

Threadहालाँकि, UI के साथ इंटरैक्ट नहीं कर सकता है, और अधिक "बेसिक" थ्रेडिंग प्रदान करता है और आप के सभी सार को याद करते हैं AsyncTask

हालाँकि, मैं एक सॉकेट कनेक्शन को सेवा में चलाना चाहूंगा। क्या इसे हैंडलर या थ्रेड में चलाया जाना चाहिए, या ए भी AsyncTask? यूआई इंटरैक्शन बिल्कुल भी आवश्यक नहीं है। क्या यह प्रदर्शन के मामले में फर्क करता है जो मैं उपयोग करता हूं?

इस बीच, प्रलेखन में व्यापक सुधार हुआ है।



9
"हैंडलर्स बैकग्राउंड थ्रेड हैं" - कुछ शीर्ष वोटों वाले उत्तर उस दिशा में भी जाते हैं। लेकिन यह एक गलत धारणा है। A Handlerएक धागा नहीं है, और यह कुछ भी निष्पादित नहीं करता है। यह केवल एक साधन के सुरक्षित रूप से एक से संदेश पारित करने के लिए है धागा दूसरे के संदेश कतार में धागा । तो, आम तौर पर, (कम से कम) दो धागे अभी भी बनाए जाने चाहिए जो तब एक हैंडलर का उपयोग कर सकते हैं , लेकिन हैंडलर स्वयं कुछ भी निष्पादित नहीं कर सकता है।
जिमीबी

जवाबों:


57

हैंडलर, AsyncTask और वोगेला साइट पर लोडर्स के साथ एंड्रॉइड बैकग्राउंड प्रोसेसिंग पर ट्यूटोरियल इसे डालता है:

Handlerवर्ग एक धागा करने के लिए रजिस्टर करने के लिए इस्तेमाल किया जा सकता है और इस धागे को डेटा भेजने के एक साधारण चैनल प्रदान करता है।

AsyncTaskवर्ग एक पृष्ठभूमि प्रक्रिया के निर्माण और मुख्य थ्रेड के साथ तुल्यकालन समाहित। यह रनिंग कार्यों की रिपोर्टिंग प्रगति का भी समर्थन करता है।

और Threadमूल रूप से मल्टीथ्रेडिंग का मूल तत्व है जिसे एक डेवलपर निम्नलिखित नुकसान के साथ उपयोग कर सकता है:

यदि आप जावा थ्रेड का उपयोग करते हैं, तो आपको अपने कोड में निम्नलिखित आवश्यकताओं को संभालना होगा:

  • यदि आप उपयोगकर्ता इंटरफ़ेस पर वापस परिणाम पोस्ट करते हैं तो मुख्य सूत्र के साथ सिंक्रनाइज़ेशन
  • धागा रद्द करने के लिए कोई डिफ़ॉल्ट नहीं
  • कोई डिफ़ॉल्ट थ्रेड पूलिंग नहीं
  • Android में कॉन्फ़िगरेशन परिवर्तन से निपटने के लिए कोई डिफ़ॉल्ट नहीं है

और इसके बारे में AsyncTask, जैसा कि Android डेवलपर के संदर्भ में है:

AsyncTaskUI थ्रेड का उचित और आसान उपयोग सक्षम करता है। यह वर्ग थ्रेड और / या हैंडलर में हेरफेर किए बिना पृष्ठभूमि संचालन करने और UI थ्रेड पर परिणाम प्रकाशित करने की अनुमति देता है।

AsyncTaskएक सहायक वर्ग के चारों ओर बनाया गया है Threadऔर Handler और एक सामान्य सूत्रण ढांचे का गठन नहीं है। AsyncTasks को लघु संचालन के लिए उपयोग किया जाना चाहिए (कुछ सेकंड सबसे अधिक।) यदि आपको लंबे समय तक चलने वाले थ्रेड रखने की आवश्यकता है, तो यह अत्यधिक अनुशंसा की जाती है कि आप java.util.concurrent द्वारा प्रदान किए गए विभिन्न API का उपयोग करें। निष्पादक, थ्रेडपूल एक्ज़ीक्यूटर और FutureTask।

मई 2015 को अपडेट करें: मुझे इस विषय को कवर करने वाले व्याख्यान की एक उत्कृष्ट श्रृंखला मिली ।

यह Google खोज है: डगलस श्मिट व्याख्यान Android संगामिति और सिंक्रनाइज़ेशन

यह YouTube पर पहले व्याख्यान का वीडियो है

यह सब सीएस 282 (2013) का हिस्सा है : वेंडरबिल्ट यूनिवर्सिटी से एंड्रॉइड के लिए सिस्टम प्रोग्रामिंग । यहाँ YouTube Playlist है

डगलस श्मिट एक उत्कृष्ट व्याख्याता लगता है

महत्वपूर्ण: यदि आप एक ऐसे बिंदु पर हैं जहां आप AsyncTaskअपने थ्रेडिंग मुद्दों को हल करने के लिए उपयोग करने के लिए विचार कर रहे हैं, तो आपको पहले संभवतः अधिक सटीक प्रोग्रामिंग पैटर्न की जांचReactiveX/RxAndroid करनी चाहिए । अवलोकन के लिए एक बहुत अच्छा संसाधन उदाहरण के लिए Android के लिए RxJava 2 सीखना है


4
उस व्याख्यान श्रृंखला में, यह लिंक आपको कुछ थ्रेड उदाहरणों में सही ले जाएगा: youtu.be/4Vue_KuXfCk?t=19m24s
Aggressor

353

यदि हम स्रोत कोड को देखते हैं, तो हम देखेंगे AsyncTaskऔर Handlerविशुद्ध रूप से जावा में लिखा है। (हालांकि कुछ अपवाद हैं, लेकिन यह एक महत्वपूर्ण बिंदु नहीं है)

तो वहाँ में कोई जादू नहीं है AsyncTaskया Handler। ये कक्षाएं एक डेवलपर के रूप में हमारे जीवन को आसान बनाती हैं।

उदाहरण के लिए: यदि प्रोग्राम A कॉल विधि A (), मेथड A () प्रोग्राम A के साथ किसी भिन्न थ्रेड में चला सकता है। हम कोड का पालन करते हुए आसानी से सत्यापित कर सकते हैं:

Thread t = Thread.currentThread();    
int id = t.getId();

हमें कुछ कार्यों के लिए नए थ्रेड का उपयोग क्यों करना चाहिए? आप इसके लिए google कर सकते हैं। कई कारण, उदाहरण के लिए: भारी, लंबे समय तक चलने वाले कार्यों को उठाना।

तो, के बीच मतभेद रहे हैं Thread, AsyncTaskऔर Handler?

AsyncTaskऔर Handlerजावा में लिखा है (आंतरिक रूप से वे एक का उपयोग करते हैं Thread), इसलिए हम जो कुछ भी कर सकते हैं Handlerया AsyncTask, हम Threadभी एक का उपयोग करके प्राप्त कर सकते हैं।

क्या Handlerऔर AsyncTaskवास्तव में मदद कर सकता है ?

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

इसलिए हमें उपयोग करना चाहिए Handlerऔर AsyncTask। ये कक्षाएं हमारे लिए ज्यादातर काम करती हैं, हमें केवल यह जानने की जरूरत है कि किन तरीकों को ओवरराइड करना है।

के बीच का अंतर Handlerऔर AsyncTaskहै: का प्रयोग करें AsyncTaskजब कोलर धागा एक है यूआई धागा । यह वही है जो android दस्तावेज़ कहता है:

AsyncTask UI थ्रेड का उचित और आसान उपयोग सक्षम करता है। यह वर्ग थ्रेड और / या हैंडलर में हेरफेर किए बिना पृष्ठभूमि संचालन करने और UI थ्रेड पर परिणाम प्रकाशित करने की अनुमति देता है

मैं दो बिंदुओं पर जोर देना चाहता हूं:

1) यूआई थ्रेड का आसान उपयोग (इसलिए, कॉलर थ्रेड यूआई थ्रेड का उपयोग करें)।

2) हैंडलर में हेरफेर करने की कोई जरूरत नहीं है। (इसका मतलब है: आप AsyncTask के बजाय हैंडलर का उपयोग कर सकते हैं, लेकिन AsyncTask एक आसान विकल्प है)।

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

@: जब आप Android दस्तावेज़ पढ़ते हैं, तो आप देखेंगे:

हैंडलर आपको एक थ्रेड के MessageQueue से जुड़े संदेश और Runnable ऑब्जेक्ट को भेजने और संसाधित करने की अनुमति देता है

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

उलझा हुआ? बस याद रखें कि Handlerकॉलर थ्रेड से सुरक्षित रूप से संवाद कर सकते हैं।


4
वास्तव में asynctask भी हैंडलर और Futuretask पर आधारित है, देखें
सुमित

AsyncTask मूलतः हैंडलर और थ्रेड के शीर्ष पर बनाया गया एक सहायक वर्ग है। developer.android.com/reference/android/os/AsyncTask.html । डॉक्टर को देखें "AsyncTask को थ्रेड और हैंडलर के आसपास एक सहायक वर्ग के रूप में तैयार किया गया है"। AsyncTask को API3 में जारी किया गया जबकि हैंडलर API1 के बाद से मौजूद है।
2

52

गहराई से देखने के बाद, यह सीधे आगे है।

AsyncTask:

यह जावा धागा मॉडल के बारे में कुछ भी जाने बिना एक धागे का उपयोग करने का एक सरल तरीका है । AsyncTaskवर्कर थ्रेड और मेन थ्रेड से संबंधित विभिन्न कॉलबैक देता है।

निम्नलिखित जैसे छोटे वेटिंग ऑपरेशन के लिए उपयोग करें:

  1. वेब सेवाओं से कुछ डेटा प्राप्त करना और लेआउट पर प्रदर्शित करना।
  2. डेटाबेस क्वेरी।
  3. जब आपको पता चलता है कि रनिंग ऑपरेशन कभी भी, कभी भी नेस्टेड नहीं होगा।

Handler:

जब हम Android में कोई एप्लिकेशन इंस्टॉल करते हैं, तो यह MAIN UI थ्रेड नामक उस एप्लिकेशन के लिए एक थ्रेड बनाता है। सारी गतिविधियाँ उस धागे के अंदर चलती हैं। एंड्रॉइड सिंगल थ्रेड मॉडल नियम द्वारा, हम उस गतिविधि के अंदर परिभाषित एक और थ्रेड के लिए सीधे यूआई तत्वों (बिटमैप, टेक्स्टव्यू, आदि) तक नहीं पहुंच सकते हैं।

एक हैंडलर आपको अन्य पृष्ठभूमि थ्रेड्स से UI थ्रेड के साथ वापस संचार करने की अनुमति देता है। यह एंड्रॉइड में उपयोगी है क्योंकि एंड्रॉइड अन्य थ्रेड को यूआई थ्रेड के साथ सीधे संवाद करने की अनुमति नहीं देता है। एक हैंडलर संदेश और Runnable ऑब्जेक्ट्स को एक थ्रेड के MessageQueue के साथ भेज और संसाधित कर सकता है। प्रत्येक हैंडलर का उदाहरण एकल थ्रेड और उस थ्रेड संदेश पंक्ति के साथ जुड़ा हुआ है। जब एक नया हैंडलर बनाया जाता है, तो यह उस थ्रेड के संदेश / संदेश कतार से जुड़ा होता है, जो इसे बना रहा है।

यह इसके लिए सबसे उपयुक्त है:

  1. यह आपको संदेश पंक्तिबद्ध करने की अनुमति देता है।
  2. संदेश समयबद्धन।

Thread:

अब धागे के बारे में बात करने का समय है।

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


1
AsyncTask एपीआई, वास्तव में, फ्यूचर्स, हैंडलर और एक्जिक्यूटर्स के साथ लिखा गया है। स्रोत कोड देखें: grepcode.com/file_/repository.grepcode.com/java/ext/…
IgGanapolsky

22

एक AsyncTaskका उपयोग कुछ पृष्ठभूमि संगणना करने के लिए किया जाता है और परिणाम को UI थ्रेड (वैकल्पिक प्रगति अपडेट के साथ) में प्रकाशित किया जाता है। चूंकि आप यूआई से चिंतित नहीं हैं, तो एक Handlerया Threadअधिक उपयुक्त लगता है।

आप एक पृष्ठभूमि अंडे कर सकते हैं Threadऔर संदेशों का उपयोग करके अपने मुख्य थ्रेड पर वापस पारित Handlerकी postविधि।


9

धागा

Android मानक जावा थ्रेड्स का समर्थन करता है । आप java.util.concurrentपृष्ठभूमि में कार्रवाई करने के लिए मानक थ्रेड्स और पैकेज से उपकरण " " का उपयोग कर सकते हैं । केवल सीमा यह है कि आप पृष्ठभूमि प्रक्रिया से UI को सीधे अपडेट नहीं कर सकते हैं।

यदि आपको पृष्ठभूमि कार्य से यूआई को अपडेट करने की आवश्यकता है, तो आपको कुछ एंड्रॉइड विशिष्ट वर्गों का उपयोग करने की आवश्यकता है। आप वर्ग "का उपयोग कर सकते android.os.Handler" इस या वर्ग के लिए " AsyncTask"

हैंडलर

वर्ग " Handler" यूआई को अपडेट कर सकता है। एक हैंडल संदेश प्राप्त करने और रनवेबल्स के लिए तरीके प्रदान करता है। एक हैंडलर का उपयोग करने के लिए आपको इसे उप-लिंक करना होगा और handleMessage()संदेशों को संसाधित करने के लिए ओवरराइड करना होगा। प्रक्रिया के लिए Runable, आप उस विधि का उपयोग कर सकते हैं जिसे post();आपको अपनी गतिविधि में केवल एक हैंडलर की आवश्यकता है।

आप थ्रेड विधि sendMessage(Message msg)या के माध्यम से संदेश पोस्ट कर सकते हैं sendEmptyMessage

AsyncTask

यदि आपके पास Activityसामग्री डाउनलोड करने या संचालन करने की आवश्यकता है जो पृष्ठभूमि में किया जा सकता है, तो AsyncTaskआप एक उत्तरदायी उपयोगकर्ता इंटरफ़ेस बनाए रख सकते हैं और उपयोगकर्ता के लिए उन कार्यों के लिए प्रगति प्रकाशित कर सकते हैं।

अधिक जानकारी के लिए आप इन लिंक को देख सकते हैं।

http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/

http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask


6

Thread:

Threadयूआई थ्रेड को प्रभावित किए बिना आप लंबे समय तक चलने वाले पृष्ठभूमि कार्यों के लिए नए का उपयोग कर सकते हैं । जावा थ्रेड से, आप UI थ्रेड को अपडेट नहीं कर सकते।

चूंकि एंड्रॉइड आर्किटेक्चर के लिए सामान्य थ्रेड बहुत उपयोगी नहीं है, इसलिए थ्रेडिंग के लिए सहायक कक्षाएं शुरू की गई हैं।

आप थ्रेडिंग प्रदर्शन प्रलेखन पृष्ठ में अपने प्रश्नों के उत्तर पा सकते हैं ।

हैंडलर :

A Handlerआपको Runnableएक थ्रेड से जुड़े संदेश और ऑब्जेक्ट भेजने और संसाधित करने की अनुमति देता है MessageQueue। प्रत्येक Handlerउदाहरण एक धागे से जुड़ा होता है और उस धागे की संदेश कतार।

एक के लिए दो मुख्य उपयोग हैं Handler:

  1. भविष्य में कुछ बिंदु के रूप में निष्पादित किए जाने वाले संदेशों और रनवे को शेड्यूल करने के लिए;

  2. अपने दम से एक अलग धागे पर प्रदर्शन किया जा करने के लिए एक कार्रवाई।

AsyncTask :

AsyncTaskUI थ्रेड का उचित और आसान उपयोग सक्षम करता है। यह वर्ग आपको थ्रेड और / या हैंडलर में हेरफेर किए बिना पृष्ठभूमि संचालन करने और UI थ्रेड पर परिणाम प्रकाशित करने की अनुमति देता है।

कमियां:

  1. डिफ़ॉल्ट रूप से, एक ऐप सभी AsyncTaskवस्तुओं को धक्का देता है जो इसे एक ही धागे में बनाता है। इसलिए, वे धारावाहिक फैशन पर अमल करते हैं, और मुख्य धागे के साथ-एक विशेष रूप से लंबे काम के पैकेट कतार को अवरुद्ध कर सकते हैं। इस कारण के कारण, 5 मिनट से कम अवधि के काम की वस्तुओं को संभालने के लिए AsyncTask का उपयोग करें ।

  2. AsyncTaskऑब्जेक्ट भी अंतर्निहित-संदर्भ मुद्दों के लिए सबसे आम अपराधी हैं। AsyncTaskवस्तुएं स्पष्ट संदर्भों के साथ-साथ जोखिम भी प्रस्तुत करती हैं।

हैंडलरथ्रेड :

आपको लंबे समय तक चलने वाले थ्रेड पर काम के ब्लॉक को निष्पादित करने के लिए अधिक पारंपरिक दृष्टिकोण की आवश्यकता हो सकती है ( AsyncTask के विपरीत, जिसका उपयोग 5ms वर्कलोड के लिए किया जाना चाहिए ), और मैन्युअल रूप से उस वर्कफ़्लो को प्रबंधित करने की कुछ क्षमता। एक हैंडलर धागा प्रभावी रूप से लंबे समय तक चलने वाला धागा है जो एक कतार से काम करता है और उस पर काम करता है।

ThreadPoolExecutor :

यह वर्ग थ्रेड्स के एक समूह के निर्माण का प्रबंधन करता है, उनकी प्राथमिकताएं निर्धारित करता है, और उन थ्रेड्स के बीच काम कैसे वितरित किया जाता है, का प्रबंधन करता है। जैसे ही कार्यभार बढ़ता या घटता है, वर्ग कार्यभार को समायोजित करने के लिए अधिक थ्रेड्स को नष्ट या नष्ट कर देता है।

यदि कार्यभार अधिक है और एकल HandlerThreadपर्याप्त नहीं है, तो आप जा सकते हैंThreadPoolExecutor

हालाँकि मैं एक सॉकेट कनेक्शन सेवा में चलाना चाहूंगा। क्या यह एक हैंडलर या एक थ्रेड या एक AsyncTask में चलाया जाना चाहिए? यूआई इंटरैक्शन बिल्कुल भी आवश्यक नहीं है। क्या यह प्रदर्शन के मामले में फर्क करता है जो मैं उपयोग करता हूं?

चूंकि UI इंटरैक्शन की आवश्यकता नहीं है, इसलिए आप इसके लिए नहीं जा सकते हैं AsyncTask। सामान्य धागे ज्यादा उपयोगी नहीं होते हैं और इसलिए HandlerThreadयह सबसे अच्छा विकल्प है। चूंकि आपको सॉकेट कनेक्शन बनाए रखना है, मुख्य धागे पर हैंडलर बिल्कुल उपयोगी नहीं है। बनाएँ HandlerThreadऔर Handlerके लूपर से प्राप्त करें HandlerThread

 HandlerThread handlerThread = new HandlerThread("SocketOperation");
 handlerThread.start();
 Handler requestHandler = new Handler(handlerThread.getLooper());
 requestHandler.post(myRunnable); // where myRunnable is your Runnable object. 

यदि आप UI थ्रेड पर वापस संचार करना चाहते हैं, तो आप प्रतिक्रिया को संसाधित करने के लिए एक और हैंडलर का उपयोग कर सकते हैं।

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Foreground task is completed:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

अपने में Runnable, आप जोड़ सकते हैं

responseHandler.sendMessage(msg);

कार्यान्वयन के बारे में अधिक विवरण यहां पाया जा सकता है:

Android: एक धागे में टोस्ट


5

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

अपडेट करें

कृपया मेरे उपरोक्त उत्तर की अवहेलना करें! मैंने 2011 में इस सवाल का जवाब दिया जब मैं अब तक एंड्रॉइड में कम अनुभवी था। ऊपर दिया गया मेरा उत्तर भ्रामक है और इसे गलत माना जाता है। मैं इसे वहां छोड़ रहा हूं क्योंकि कई लोगों ने मुझे सही करने के लिए नीचे टिप्पणी की, और मैंने अपना सबक सीखा है।

इस थ्रेड पर अन्य बेहतर उत्तर हैं, लेकिन मैं कम से कम मुझे अधिक उचित उत्तर दूंगा। नियमित जावा का उपयोग करने में कुछ भी गलत नहीं है Thread; हालाँकि, आपको वास्तव में इस बारे में सावधान रहना चाहिए कि आप इसे कैसे लागू करते हैं क्योंकि यह गलत करना बहुत प्रोसेसर गहन हो सकता है (सबसे उल्लेखनीय लक्षण आपके डिवाइस को गर्म करना हो सकता है)। AsyncTasks अधिकांश कार्यों के लिए आदर्श हैं जिन्हें आप पृष्ठभूमि में चलाना चाहते हैं (सामान्य उदाहरण डिस्क I / O, नेटवर्क कॉल और डेटाबेस कॉल हैं)। हालाँकि, AsyncTasks का उपयोग विशेष रूप से लंबी प्रक्रियाओं के लिए नहीं किया जाना चाहिए जो उपयोगकर्ता द्वारा आपके ऐप को बंद करने या उनके डिवाइस को स्टैंडबाय में रखने के बाद जारी रखने की आवश्यकता हो सकती है। मैं ज्यादातर मामलों के लिए कहूंगा, जो कुछ भी यूआई थ्रेड में नहीं है, उसका ध्यान रखा जा सकता है AsyncTask


धन्यवाद, क्या वास्तव में एक कारण है जो मुझे AsyncTasks के बजाय थ्रेड्स का उपयोग करना चाहिए? या क्या इसका उपयोग करने की अधिक अनुशंसा की जाती है?
अल्क्स

9
@AeroDroid आपके उदाहरण में: "एक सरल (सच्चा)", आप CPU को यहाँ पेग करेंगे जब तक कि आप लूप में स्लीप स्टेट नहीं जोड़ते। यह किसी भी अंतहीन लूप का सच है। यदि आप इस ओवरहेड के कारण सीपीयू उपयोग को कम करना चाहते हैं, तो लूप के अंत में कुछ मिलीसेकंड के लिए थ्रेड को सोएं।
एरोड 454

1
@Error 454 - यह दिलचस्प है! यदि आपको सोने के समय के लिए उचित संख्या चुननी है, तो क्या यह 40-80 मिलीसेकंड के बीच होगी?
अभिजीत

6
@ अभिजीत ने एसडीएल में किए गए खेल के सामान से, बेकार अवस्थाओं के दौरान 99% सीपीयू से ~ 0 तक ड्रॉप करने के लिए बस 10 एमएस की नींद को लूप में जोड़ने के लिए पर्याप्त था।
त्रुटि 454

15
असल में developer.android.com/reference/android/os/AsyncTask.html कहता है: "AsyncTasks को आदर्श रूप से SHORT संचालन के लिए उपयोग किया जाना चाहिए"। आपको उन्हें सावधानीपूर्वक उपयोग करना चाहिए क्योंकि सिस्टम द्वारा निष्पादित किए बिना उन्हें खारिज कर दिया जा सकता है!
टाइप- a1pha

5

AsyncTaskपृष्ठभूमि में किए जाने वाले कुछ सेकंड के संचालन से अधिक नहीं करने के लिए डिज़ाइन किया गया है (सर्वर से फ़ाइल डाउनलोड करने के मेगाबाइट के लिए अनुशंसित नहीं है या सीपीयू गहन कार्य जैसे फ़ाइल आईओ संचालन की गणना करें)। यदि आपको लंबे समय तक चलने वाले ऑपरेशन को निष्पादित करने की आवश्यकता है, तो आपको जावा देशी धागे का उपयोग करने की दृढ़ता से सलाह दी गई है। जावा आपको विभिन्न थ्रेड संबंधित कक्षाएं देता है जो आपको चाहिए। Handlerयूआई थ्रेड को अपडेट करने के लिए उपयोग करें ।


2
public class RequestHandler {

    public String sendPostRequest(String requestURL,
                                  HashMap<String, String> postDataParams) {

        URL url;

        StringBuilder sb = new StringBuilder();
        try {
            url = new URL(requestURL);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);


            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));

            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();

            if (responseCode == HttpsURLConnection.HTTP_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                sb = new StringBuilder();
                String response;
                while ((response = br.readLine()) != null){
                    sb.append(response);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }

        return result.toString();
    }

}

1

मुझे एक उदाहरण के साथ प्रश्न का उत्तर देने की कोशिश करें :) - MyImageSearch [कृपया मुख्य गतिविधि स्क्रीन की छवि को देखें - जिसमें एक संपादित पाठ / खोज बटन / ग्रिड दृश्य है]

MyImageSearch

MyImageSearch का विवरण - एक बार जब उपयोगकर्ता संपादित पाठ फ़ील्ड पर विवरण दर्ज करता है और खोज बटन पर क्लिक करता है, तो हम फ़्लिकर द्वारा प्रदान की गई वेब सेवाओं के माध्यम से इंटरनेट पर छवियां खोजेंगे (आपको कुंजी / गुप्त टोकन प्राप्त करने के लिए केवल वहां पंजीकरण करने की आवश्यकता है) - हम खोज के लिए HTTP रिक्वेस्ट भेजते हैं और JSON डेटा को अलग-अलग छवियों के url के जवाब में वापस भेजते हैं जिसे हम फिर ग्रिड व्यू को लोड करने के लिए उपयोग करेंगे।

मेरा कार्यान्वयन - मुख्य गतिविधि में, मैं एक आंतरिक वर्ग को परिभाषित करूंगा, जो DoInBackGround मे HTTP अनुरोध भेजने के लिए AsyncTask का विस्तार करता है और JSON रिस्पांस प्राप्त करता है और फ़्लिकर एडेप्टर के माध्यम से अपने GridView को अद्यतन करने के लिए उपयोग करने जा रहा हूं, जो फ़्लिकरग्रुप के मेरे स्थानीय एरेलेस्ट को अपडेट करता है। (बेस एडेप्टर का विस्तार करता है) और ग्रिड दृश्य को पुनः लोड करने के लिए AsyncTask के onPostExecute () के onPostExecute () में एडेप्टर .notifyDataSetChanged () कॉल करें। ध्यान दें कि यहाँ HTTP अनुरोध एक अवरुद्ध कॉल है, जिसके कारण मैंने इसे AsyncTask के माध्यम से किया है। और, मैं एडॉप्टर में आइटम को कैश कर सकता हूं ताकि प्रदर्शन को बढ़ाया जा सके या उन्हें एसडीकार्ड पर स्टोर किया जा सके। फ़्लिकर एडेप्टर में जो ग्रिड मैं फुलाया जा रहा है उसमें मेरे कार्यान्वयन में प्रगतिशीलता और छवि दृश्य शामिल हैं। नीचे आप mainActivity के लिए कोड पा सकते हैं जो मैंने इस्तेमाल किया था।

अब प्रश्न का उत्तर दें - इसलिए एक बार व्यक्तिगत छवियों को प्राप्त करने के लिए हमारे पास JSON डेटा है जिसे हम हैंडलर या थ्रेड्स या AsyncTask के माध्यम से पृष्ठभूमि में छवियों को प्राप्त करने के तर्क को लागू कर सकते हैं। हमें यहां ध्यान देना चाहिए कि चूंकि मेरी छवियां एक बार डाउनलोड की गई UI / मुख्य थ्रेड पर प्रदर्शित होनी चाहिए, इसलिए हम केवल थ्रेड का उपयोग नहीं कर सकते क्योंकि यह संदर्भ तक पहुंच नहीं है। फ़्लिकर एडेप्टर में, मैं जिन विकल्पों के बारे में सोच सकता था:

  • विकल्प 1: एक LooperThread बनाएँ [धागे का विस्तार करें] - और इस धागे को खुला रखकर एक धागे में क्रमिक रूप से छवियों को डाउनलोड करते रहें [looper.loop ()]
  • विकल्प 2: एक थ्रेड पूल का उपयोग करें और myHandler के माध्यम से रनवेबल को पोस्ट करें जिसमें मेरे ImageView का संदर्भ है, लेकिन चूंकि ग्रिड व्यू में विचारों को पुनर्नवीनीकरण किया जाता है, फिर से समस्या उत्पन्न हो सकती है जहां सूचकांक 4 पर छवि सूचकांक 9 पर प्रदर्शित होती है - डाउनलोड हो सकता है अधिक समय लें]
  • च्वाइस 3 [मैंने इसका इस्तेमाल किया]: थ्रेड पूल का उपयोग करें और myHandler को एक संदेश भेजें, जिसमें खुद ImageView के सूचकांक और ImageView से संबंधित डेटा होता है, इसलिए हैंडलमैसेज करते समय () हम ImageView को केवल तभी अपडेट करेंगे जब करंटेक्सेक्स के सूचकांक से मेल खाता हो छवि हमने डाउनलोड करने का प्रयास किया।
  • विकल्प 4: पृष्ठभूमि में छवियों को डाउनलोड करने के लिए AsyncTask का उपयोग करें, लेकिन यहां मुझे थ्रेड पूल में वांछित थ्रेड्स की संख्या तक पहुंच नहीं होगी और यह अलग-अलग एंड्रॉइड वर्जन के साथ बदलता रहता है, लेकिन च्वाइस 3 में मैं सचेत निर्णय ले सकता हूं उपयोग किए जा रहे डिवाइस कॉन्फ़िगरेशन के आधार पर थ्रेड पूल का आकार।

यहाँ स्रोत कोड:

public class MainActivity extends ActionBarActivity {

    GridView imageGridView;
    ArrayList<FlickrItem> items = new ArrayList<FlickrItem>();
    FlickrAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageGridView = (GridView) findViewById(R.id.gridView1);
        adapter = new FlickrAdapter(this, items);
        imageGridView.setAdapter(adapter);
    }

    // To avoid a memory leak on configuration change making it a inner class
    class FlickrDownloader extends AsyncTask<Void, Void, Void> {



        @Override
        protected Void doInBackground(Void... params) {
            FlickrGetter getter = new FlickrGetter();

            ArrayList<FlickrItem> newItems = getter.fetchItems();

            // clear the existing array
            items.clear();

            // add the new items to the array
            items.addAll(newItems);

            // is this correct ? - Wrong rebuilding the list view and should not be done in background
            //adapter.notifyDataSetChanged();

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            adapter.notifyDataSetChanged();
        }

    }

    public void search(View view) {
        // get the flickr data
        FlickrDownloader downloader = new FlickrDownloader();
        downloader.execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

मुझे उम्मीद है कि मेरा जवाब हालांकि लंबे समय तक कुछ बारीक विवरणों को समझने में मदद करेगा।


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

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

@ 80leaves ठीक है अब मैं बात कर रहा हूं, मैंने यह समझाने की कोशिश की कि मैं कैसे एक रास्ते को दूसरे पर चुनने के निष्कर्ष पर आया। वैसे भी, अपने / दूसरों के विचारों को सुनना पसंद करेंगे कि मैंने जो लिखा है वह सही है या अगर इसे और बेहतर बनाया जा सकता है।
अक्षयमणि

1

यह निर्भर करता है कि कौन सा चुना जाना आवश्यकता पर आधारित है

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

यदि हैंडलर मेन थ्रेड के अलावा अन्य में बनाया गया है जो लूपर नहीं है, तो एरर नहीं देगा क्योंकि हैंडल थ्रेड बनाया जाता है, उस थ्रेड को लूपर बनाने की आवश्यकता होती है

AsyncTask का उपयोग कुछ सेकंड के लिए कोड निष्पादित करने के लिए किया जाता है, जो पृष्ठभूमि थ्रेड पर चलता है और इसका परिणाम मुख्य थ्रेड ** * देता है। AsyncTask सीमाएं 1. Async टास्क गतिविधि के जीवन चक्र से जुड़ा नहीं है और यह चलता रहता है, भले ही इसकी गतिविधि नष्ट हो जाए, जबकि लोड नहीं करता है 't' में यह सीमा है। 2. सभी Async टास्क निष्पादन के लिए एक ही बैकग्राउंड थ्रेड साझा करते हैं जो ऐप के प्रदर्शन को भी प्रभावित करता है

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


0

धागा

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

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

इसे रोकने के लिए, आप वर्कर थ्रेड बना सकते हैं और बैकग्राउंड या लॉन्ग रनिंग टास्क चला सकते हैं।

हैंडलर

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

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

AsyncTask

Android द्वारा प्रदान किया गया AsyncTask बैकग्राउंड में सरल कार्य करने के लिए थ्रेड और हैंडलर दोनों का उपयोग करता है और परिणाम को बैकग्राउंड थ्रेड से मुख्य थ्रेड तक आसान बनाता है।

कृपया उदाहरण के लिए एंड्रॉइड थ्रेड, हैंडलर, एसिंक्टस्क और थ्रेड पूल देखें


-1

Handler- थ्रेड्स के बीच संचार माध्यम है। एंड्रॉइड में इसका उपयोग मुख्य रूप से हैंडलर के माध्यम से संदेश बनाने और भेजने के लिए मुख्य धागे के साथ संवाद करने के लिए किया जाता है

AsyncTask- पृष्ठभूमि थ्रेड में लंबे समय तक चलने वाले एप्लिकेशन को निष्पादित करने के लिए उपयोग किया जाता है। N के साथ AsyncTaskआप बैकग्राउंड थ्रेड में ऑपरेशन कर सकते हैं और एप्लिकेशन के मुख्य थ्रेड में परिणाम प्राप्त कर सकते हैं।

Thread- एक हल्की वजन प्रक्रिया है, जो संगामिति और अधिकतम सीपीयू उपयोग को प्राप्त करने के लिए है। एंड्रॉइड में आप थ्रेड का उपयोग उन गतिविधियों को करने के लिए कर सकते हैं जो ऐप के यूआई को नहीं छूती हैं

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