ForceLayout (), requestLayout () और अमान्य () का उपयोग


185

मैं थोड़ा की भूमिकाओं के बारे में उलझन में हूँ forceLayout(), requestLayout()और invalidate()के तरीकों Viewवर्ग।

उन्हें कब बुलाया जाएगा?

जवाबों:


357

फ्रांकोइस बॉर्लीक्स और डाल्विक द्वारा प्रदान किए गए उत्तर को बेहतर ढंग से समझने के लिए, मेरा सुझाव है कि आप अर्पित माथुर द्वारा इस भयानक दृश्य जीवनचक्र आरेख पर एक नज़र डालें : यहां छवि विवरण दर्ज करें


28
मैं अक्सर अनुरोध देखता हूं कि अमान्य कहे जाने के बाद सीधे कॉल किया जा रहा है, मैं यह भी देखता हूं कि टेक्स्ट व्यू जैसी चीजों के लिए एंड्रॉइड सोर्स कोड में हो रहा है, लेकिन इस आरेख के अनुसार ऐसा करना बेमानी है, है ना? तो क्या ऐसा करने का कोई उद्देश्य है?
tcox

5
खैर यह एक दिलचस्प सवाल है, और ईमानदार होने के लिए मुझे वास्तव में नहीं पता कि वे दोनों तरीकों को क्यों कहते हैं TextView। मुझे लगता है कि सोचा कि शायद वे आकर्षित करने के लिए चाहते हैं Viewइससे पहले कि वे अपने लेआउट से संबंधित पैरामीटर बदल आखिरी बार है, लेकिन यह वास्तव में किसी भी मतलब नहीं है अगर हम उन कॉल भिन्न क्रम में लागू किया जा रहा है के बारे में सोचना (और वे कहते हैं invalidate()सही होने के बाद requestLayout()में TextViewभी)। शायद यह StackOverflow पर एक और सवाल का हकदार है :)?
बार्टेक लिपिंस्की

14
(१/२) : मुझे नहीं लगता कि आप उन दो तरीकों ( invalidate()और requestLayout()) को ठीक से समझते हैं । उन तरीकों का उद्देश्य यह बताना है कि Viewकिस प्रकार का अमान्यकरण (जैसा आपने इसे कहा था) हुआ है। यह Viewतय करने जैसा नहीं है कि उन तरीकों में से एक को कॉल करने के बाद आपको किस रास्ते पर चलना है। View-Lifecycle-path को चुनने के पीछे तर्क है कि खुद को कॉल करने के लिए उचित विधि का चयन। यदि आकार परिवर्तन से संबंधित कोई चीज है - requestLayout()तो उसे कॉल किया जाना चाहिए, यदि कोई दृश्य परिवर्तन केवल आकार में परिवर्तन के बिना है - आपको कॉल करना चाहिए invalidate()
Bartek Lipinski

11
(2/2): यदि आप अपने के आकार बदलते हैं तो Viewकिसी तरह से है, जैसे आप वर्तमान मिलता हैLayoutParams एक के Viewऔर आप उन्हें संशोधित, लेकिन नहीं फोन या तो requestLayoutया setLayoutParams(जो कॉल requestLayoutआंतरिक रूप से), तो आप कॉल कर सकते हैं invalidate()के रूप में आप चाहते हैं जितना, और यह Viewमाप-लेआउट प्रक्रिया से नहीं गुजरेगा, इसलिए इसका आकार नहीं बदलेगा। यदि आप यह नहीं बताते हैं Viewकि इसका आकार बदल गया है (एक requestLayoutविधि कॉल के साथ), तो Viewमान लेंगे कि यह नहीं हुआ, onMeasureऔर onLayoutइसे नहीं बुलाया जाएगा।
बार्टेक लिपिंस्की

2
@tcox यहाँ और अधिक -> stackoverflow.com/questions/35279374/…
सोती

125

invalidate()

कॉलिंग invalidate()तब की जाती है जब आप किसी दृश्य का पुनः शेड्यूल करना चाहते हैं। यह onDrawअंततः (जल्द ही, लेकिन तुरंत नहीं) कहा जा रहा है। एक कस्टम दृश्य कब कॉल होगा इसका एक उदाहरण है जब एक पाठ या पृष्ठभूमि का रंग गुण बदल गया है।

दृश्य फिर से हो जाएगा लेकिन आकार नहीं बदलेगा।

requestLayout()

यदि आपके विचार में कुछ परिवर्तन होता है जो आकार को प्रभावित करेगा, तो आपको कॉल करना चाहिए requestLayout()। यह ट्रिगर करेगा onMeasureऔर onLayoutन केवल इस दृश्य के लिए बल्कि सभी तरह से पैरेंट विचारों के लिए लाइन अप करेगा।

कॉलिंग requestLayout()है एक में परिणाम की गारंटी नहींonDraw (क्या स्वीकार किए जाते हैं जवाब में चित्र का तात्पर्य के विपरीत), तो यह आमतौर पर के साथ संयुक्त है invalidate()

invalidate();
requestLayout();

इसका एक उदाहरण है जब एक कस्टम लेबल की अपनी पाठ संपत्ति बदल गई है। लेबल का आकार बदल जाएगा और इस तरह उसे फिर से तैयार और फिर से तैयार करना होगा।

forceLayout()

जब कोई ऐसा requestLayout()होता है जिसे माता-पिता के दृश्य समूह पर बुलाया जाता है, तो उसे अपने बच्चे के विचारों को हटाने और पुनः जारी करने की आवश्यकता नहीं होती है। हालांकि, अगर एक बच्चे को रीमूव और रिलेआउट में शामिल किया जाना चाहिए, तो आप forceLayout()बच्चे को कॉल कर सकते हैं । forceLayout()केवल एक बच्चे पर काम करता है यदि वह requestLayout()अपने प्रत्यक्ष माता-पिता के साथ मिलकर होता है । forceLayout()अपने आप से कॉल करने का कोई प्रभाव नहीं पड़ेगा क्योंकि यह requestLayout()व्यू ट्री को ट्रिगर नहीं करता है ।

अधिक विस्तृत विवरण के लिए इस प्रश्नोत्तर को पढ़ें forceLayout()

आगे के अध्ययन


1
लेकिन क्या यह पहले कॉल कॉल लाइकआउट () और फिर अमान्य () को अधिक अर्थ नहीं देगा?
scholt

2
@scholt, जहाँ तक मुझे पता है ताकि इस मामले ताकि आप कॉल कर सकते हैं नहीं है, requestLayout()इससे पहले कि invalidate()अगर आप चाहते हैं। न तो कोई लेआउट करता है और न ही तुरंत आकर्षित होता है। बल्कि, वे झंडे सेट करते हैं जो अंततः एक रिलेआउट और रिड्राव में परिणाम देगा।
सुरगाछ

27

यहाँ आप कुछ प्रतिक्रिया पा सकते हैं: http://developer.android.com/guide/topics/ui/how-android-draws.html

मेरे लिए एक कॉल invalidate()केवल दृश्य को requestLayout()ताज़ा करने और दृश्य को ताज़ा करने के लिए एक कॉल स्क्रीन पर दृश्य के आकार की गणना करता है।


3
कैसे के बारे में forceLayout () तो?
sdabet

@ फिडलर, यह विधि सिर्फ दो झंडे लगाती है: PFLAG_FORCE_LAYOUT और PFLAG_INVALIDATED
suitianshi

7
@suitianshi झंडे सेट करने के परिणाम क्या हैं?
सेर्गेई

1
@ संसारी परिणाम यह प्रतीत होता है कि यह ध्वज कैश को मापता है (भविष्य में उसी मापक के लिए तेजी से मापने के लिए कैश का उपयोग करता है); View.java की लाइन 18783 यहां देखें: github.com/android/platform_frameworks_base/blob/master/core/…
RhetoricalRuvim

3

आप अमान्य () का उपयोग उस दृश्य पर करते हैं जिसे आप फिर से बनाना चाहते हैं, यह अपने onDraw (Canvas c) को मंगाएगा, और requestLayout () पूरे लेआउट रेंडरिंग (माप चरण और स्थिति चरण) को फिर से चलाएगा। यदि आप रनटाइम पर चाइल्ड व्यू के आकार को बदल रहे हैं तो इसका उपयोग करना चाहिए, लेकिन केवल माता-पिता के दृष्टिकोण से बाधाओं जैसे विशेष मामलों में (मेरा मतलब है कि माता-पिता की ऊंचाई या चौड़ाई WRAP_CONTENT है और इसलिए बच्चों को फिर से लपेटने से पहले मैच को मापें)


3

यह उत्तर सही नहीं है forceLayout()

जैसा कि आप इसके कोडforceLayout() में देख सकते हैं कि यह केवल "एक रिलेआउट की जरूरत है" के रूप में दृश्य को चिह्नित करता है लेकिन यह उस रिले को न तो शेड्यूल करता है और न ही ट्रिगर करता है। भविष्य में किसी बिंदु पर किसी अन्य कारण से पैरंट्स को बिठाया गया था तब तक रिलेआउट नहीं होगा।

उपयोग करते समय एक बहुत बड़ा मुद्दा है forceLayout()और requestLayout():

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

मैं इसके क्रियान्वयन पर विचार करूंगा forceLayout()(और यह कैसे requestLayout()टूटने को प्रभावित करता है और आपको अपने कोड में कभी भी उस फ़ंक्शन का उपयोग नहीं करना चाहिए।


1
नमस्ते! आप उस मंत्र के साथ कैसे आए हैं ? क्या वह दस्तावेज कहीं है?
अज़ीज़बेकियन

1
दुर्भाग्य से यह प्रलेखित नहीं है और संभवतः इसका उद्देश्य भी नहीं है। मुझे पता चला कि कोड की जांच करके Viewऔर इस मुद्दे को स्वयं चलाकर और इसे डीबग करके।
तरल पदार्थ

फिर मैं forceLayout()एपीआई के उद्देश्य के बारे में उत्सुक हूं : यह वास्तव में एक लेआउट पास के लिए मजबूर नहीं करता है, बल्कि यह सिर्फ एक ध्वज को बदलता है जिसे अंदर देखा जा रहा हैonMeasure() , लेकिन onMeasure()जब तक requestLayout()या स्पष्ट नहीं कहा जाता है तब तक इसे नहीं View#measure()बुलाया जाएगा। इसका मतलब है, कि forceLayout()के साथ जोड़ा जाना चाहिए requestLayout()। दूसरी ओर, फिर forceLayout()भी प्रदर्शन करने की आवश्यकता क्यों है requestLayout()?
अजीजबेकियन

@azizbekian नहीं, आपको नहीं करना है। requestLayout()सब कुछ करता है जो forceLayout()करता भी है।
तरल पदार्थ

1
@Suragch याद किया कि एक, धन्यवाद! बहुत दिलचस्प विश्लेषण। का उपयोग forceLayoutकरता है समझ में आता है। इसलिए अंत में यह बहुत ही बुरी तरह से नामांकित और प्रलेखित है।
तरल पदार्थ

0

invalidate()--- onDraw()यूआई थ्रेड से

postInvalidate()--- onDraw()बैकग्राउंड थ्रेड से

requestLayout()---> onMeasure()और onLayout()और जरूरी नहीं कि onDraw()

  • महत्वपूर्ण : इस विधि को कॉल करने से कक्षा के बच्चे को प्रभावित नहीं किया जाता है।

forceLayout()---> onMeasure()और onLayout() सिर्फ अगर प्रत्यक्ष माता पिता को बुलाया requestLayout()

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