जवाबों:
फ्रांकोइस बॉर्लीक्स और डाल्विक द्वारा प्रदान किए गए उत्तर को बेहतर ढंग से समझने के लिए, मेरा सुझाव है कि आप अर्पित माथुर द्वारा इस भयानक दृश्य जीवनचक्र आरेख पर एक नज़र डालें :
TextView
। मुझे लगता है कि सोचा कि शायद वे आकर्षित करने के लिए चाहते हैं View
इससे पहले कि वे अपने लेआउट से संबंधित पैरामीटर बदल आखिरी बार है, लेकिन यह वास्तव में किसी भी मतलब नहीं है अगर हम उन कॉल भिन्न क्रम में लागू किया जा रहा है के बारे में सोचना (और वे कहते हैं invalidate()
सही होने के बाद requestLayout()
में TextView
भी)। शायद यह StackOverflow पर एक और सवाल का हकदार है :)?
invalidate()
और requestLayout()
) को ठीक से समझते हैं । उन तरीकों का उद्देश्य यह बताना है कि View
किस प्रकार का अमान्यकरण (जैसा आपने इसे कहा था) हुआ है। यह View
तय करने जैसा नहीं है कि उन तरीकों में से एक को कॉल करने के बाद आपको किस रास्ते पर चलना है। View
-Lifecycle-path को चुनने के पीछे तर्क है कि खुद को कॉल करने के लिए उचित विधि का चयन। यदि आकार परिवर्तन से संबंधित कोई चीज है - requestLayout()
तो उसे कॉल किया जाना चाहिए, यदि कोई दृश्य परिवर्तन केवल आकार में परिवर्तन के बिना है - आपको कॉल करना चाहिए invalidate()
।
View
किसी तरह से है, जैसे आप वर्तमान मिलता हैLayoutParams
एक के View
और आप उन्हें संशोधित, लेकिन नहीं फोन या तो requestLayout
या setLayoutParams
(जो कॉल requestLayout
आंतरिक रूप से), तो आप कॉल कर सकते हैं invalidate()
के रूप में आप चाहते हैं जितना, और यह View
माप-लेआउट प्रक्रिया से नहीं गुजरेगा, इसलिए इसका आकार नहीं बदलेगा। यदि आप यह नहीं बताते हैं View
कि इसका आकार बदल गया है (एक requestLayout
विधि कॉल के साथ), तो View
मान लेंगे कि यह नहीं हुआ, onMeasure
और onLayout
इसे नहीं बुलाया जाएगा।
invalidate()
कॉलिंग invalidate()
तब की जाती है जब आप किसी दृश्य का पुनः शेड्यूल करना चाहते हैं। यह onDraw
अंततः (जल्द ही, लेकिन तुरंत नहीं) कहा जा रहा है। एक कस्टम दृश्य कब कॉल होगा इसका एक उदाहरण है जब एक पाठ या पृष्ठभूमि का रंग गुण बदल गया है।
दृश्य फिर से हो जाएगा लेकिन आकार नहीं बदलेगा।
requestLayout()
यदि आपके विचार में कुछ परिवर्तन होता है जो आकार को प्रभावित करेगा, तो आपको कॉल करना चाहिए requestLayout()
। यह ट्रिगर करेगा onMeasure
और onLayout
न केवल इस दृश्य के लिए बल्कि सभी तरह से पैरेंट विचारों के लिए लाइन अप करेगा।
कॉलिंग requestLayout()
है एक में परिणाम की गारंटी नहींonDraw
(क्या स्वीकार किए जाते हैं जवाब में चित्र का तात्पर्य के विपरीत), तो यह आमतौर पर के साथ संयुक्त है invalidate()
।
invalidate();
requestLayout();
इसका एक उदाहरण है जब एक कस्टम लेबल की अपनी पाठ संपत्ति बदल गई है। लेबल का आकार बदल जाएगा और इस तरह उसे फिर से तैयार और फिर से तैयार करना होगा।
forceLayout()
जब कोई ऐसा requestLayout()
होता है जिसे माता-पिता के दृश्य समूह पर बुलाया जाता है, तो उसे अपने बच्चे के विचारों को हटाने और पुनः जारी करने की आवश्यकता नहीं होती है। हालांकि, अगर एक बच्चे को रीमूव और रिलेआउट में शामिल किया जाना चाहिए, तो आप forceLayout()
बच्चे को कॉल कर सकते हैं । forceLayout()
केवल एक बच्चे पर काम करता है यदि वह requestLayout()
अपने प्रत्यक्ष माता-पिता के साथ मिलकर होता है । forceLayout()
अपने आप से कॉल करने का कोई प्रभाव नहीं पड़ेगा क्योंकि यह requestLayout()
व्यू ट्री को ट्रिगर नहीं करता है ।
अधिक विस्तृत विवरण के लिए इस प्रश्नोत्तर को पढ़ें forceLayout()
।
requestLayout()
इससे पहले कि invalidate()
अगर आप चाहते हैं। न तो कोई लेआउट करता है और न ही तुरंत आकर्षित होता है। बल्कि, वे झंडे सेट करते हैं जो अंततः एक रिलेआउट और रिड्राव में परिणाम देगा।
यहाँ आप कुछ प्रतिक्रिया पा सकते हैं: http://developer.android.com/guide/topics/ui/how-android-draws.html
मेरे लिए एक कॉल invalidate()
केवल दृश्य को requestLayout()
ताज़ा करने और दृश्य को ताज़ा करने के लिए एक कॉल स्क्रीन पर दृश्य के आकार की गणना करता है।
आप अमान्य () का उपयोग उस दृश्य पर करते हैं जिसे आप फिर से बनाना चाहते हैं, यह अपने onDraw (Canvas c) को मंगाएगा, और requestLayout () पूरे लेआउट रेंडरिंग (माप चरण और स्थिति चरण) को फिर से चलाएगा। यदि आप रनटाइम पर चाइल्ड व्यू के आकार को बदल रहे हैं तो इसका उपयोग करना चाहिए, लेकिन केवल माता-पिता के दृष्टिकोण से बाधाओं जैसे विशेष मामलों में (मेरा मतलब है कि माता-पिता की ऊंचाई या चौड़ाई WRAP_CONTENT है और इसलिए बच्चों को फिर से लपेटने से पहले मैच को मापें)
यह उत्तर सही नहीं है forceLayout()
।
जैसा कि आप इसके कोडforceLayout()
में देख सकते हैं कि यह केवल "एक रिलेआउट की जरूरत है" के रूप में दृश्य को चिह्नित करता है लेकिन यह उस रिले को न तो शेड्यूल करता है और न ही ट्रिगर करता है। भविष्य में किसी बिंदु पर किसी अन्य कारण से पैरंट्स को बिठाया गया था तब तक रिलेआउट नहीं होगा।
उपयोग करते समय एक बहुत बड़ा मुद्दा है forceLayout()
और requestLayout()
:
मान लीजिए कि आपने forceLayout()
किसी दृश्य पर कॉल किया है। अब जब requestLayout()
उस दृश्य के वंशज पर कॉल किया जाता है, तो एंड्रॉइड पुन: requestLayout()
उस वंश के पूर्वजों को कॉल करेगा । समस्या यह है कि यह उस दृश्य पर पुनरावृत्ति को रोक देगा, जिस पर आपने कॉल किया है forceLayout()
। इसलिए requestLayout()
कॉल कभी भी व्यू रूट तक नहीं पहुंचेगी और इस तरह कभी लेआउट पास शेड्यूल नहीं किया जाएगा। दृश्य पदानुक्रम का एक पूरा उप-खंड एक लेआउट की प्रतीक्षा कर रहा है और requestLayout()
उस सबट्री के किसी भी दृश्य पर कॉल करने से लेआउट का कारण नहीं होगा। केवल requestLayout()
उस उपशीर्षक के बाहर किसी भी दृश्य पर कॉल करने से जादू टूट जाएगा।
मैं इसके क्रियान्वयन पर विचार करूंगा forceLayout()
(और यह कैसे requestLayout()
टूटने को प्रभावित करता है और आपको अपने कोड में कभी भी उस फ़ंक्शन का उपयोग नहीं करना चाहिए।
View
और इस मुद्दे को स्वयं चलाकर और इसे डीबग करके।
forceLayout()
एपीआई के उद्देश्य के बारे में उत्सुक हूं : यह वास्तव में एक लेआउट पास के लिए मजबूर नहीं करता है, बल्कि यह सिर्फ एक ध्वज को बदलता है जिसे अंदर देखा जा रहा हैonMeasure()
, लेकिन onMeasure()
जब तक requestLayout()
या स्पष्ट नहीं कहा जाता है तब तक इसे नहीं View#measure()
बुलाया जाएगा। इसका मतलब है, कि forceLayout()
के साथ जोड़ा जाना चाहिए requestLayout()
। दूसरी ओर, फिर forceLayout()
भी प्रदर्शन करने की आवश्यकता क्यों है requestLayout()
?
requestLayout()
सब कुछ करता है जो forceLayout()
करता भी है।
forceLayout
करता है समझ में आता है। इसलिए अंत में यह बहुत ही बुरी तरह से नामांकित और प्रलेखित है।
invalidate()
--- onDraw()
यूआई थ्रेड से
postInvalidate()
--- onDraw()
बैकग्राउंड थ्रेड से
requestLayout()
---> onMeasure()
और onLayout()
और जरूरी नहीं कि onDraw()
forceLayout()
---> onMeasure()
और onLayout()
सिर्फ अगर प्रत्यक्ष माता पिता को बुलाया requestLayout()
।