Yanıtlar:
Daha iyi tarafından verilen cevapları anlamak François BOURLIEUX ve Dalvik I Eğer bu müthiş görünüm yaşam döngüsü diyagramı bakmak önermek Arpit Mathur :

TextView. Onların çizmek istiyorum belki bu düşünce Viewonların düzen-ilişkili parametreleri değiştirmeden önce son kez, ama farklı sırayla çağrılan o aramalarla ilgili düşünüyorsanız gerçekten bir anlam ifade etmez (ve çağrı invalidate()sonrasında sağ requestLayout()içinde TextViewde). Belki StackOverflow :) 'da başka bir soruyu hak ediyor?
invalidate()ve requestLayout()) düzgün bir şekilde anladığınızı sanmıyorum . Bu yöntemlerin amacı (sizin adınıza) Viewne tür bir geçersiz kılma olduğunu anlatmaktır. Bu Viewyöntemlerden birini çağırdıktan sonra hangi yolu izleyeceğinize karar vermek gibi değil . View-Lifecycle-path seçiminin ardındaki mantık , kendisini çağırmak için uygun yöntemin seçilmesidir. Boyut değişikliği ile ilgili bir şey varsa - requestLayout()çağrılmalı, sadece boyut değiştirmeden görsel bir değişiklik varsa - aramalısınız invalidate().
Viewbir şekilde, örneğin size güncel olsunLayoutParams a Viewve bunları değiştirmek ancak DEĞİL ya çağrı requestLayoutveya setLayoutParams(çağıran requestLayouto zaman arayabilirsin, içten) invalidate()istediğiniz kadar kadar ve Viewdolayısıyla boyutunu değiştirmek olmaz, tedbir düzeni sürecinde gitmeyecek. ViewBoyutunuzun değiştiğini ( requestLayoutyöntem çağrısı ile) söylemezseniz, o zaman bunun değişmediğini Viewvarsayar onMeasureve onLayoutçağrılmaz.
invalidate()Arama invalidate(), görünümün yeniden çizilmesini planlamak istediğinizde yapılır. SonuçlanacakonDraw (ama hemen değil, yakında) sonunda çağrılan. Özel görünümün ne zaman çağrılacağına örnek olarak, bir metin veya arka plan rengi özelliği değişmiştir.
Görünüm yeniden çizilecek, ancak boyut değişmeyecek.
requestLayout()Görüşünüzle ilgili olarak boyutu etkileyecek bir şey değişirse, aramanız gerekir requestLayout(). Bu tetikleyecek onMeasureveonLayout ebeveyn görünümleri için çizgi yukarı yol Bu görünüm için ama hepsi değil sadece.
Aramanın requestLayout(), (kabul edilen cevaptaki şemanın ne anlama geldiğinin aksine) ile sonuçlanması garanti edilmezonDraw , bu nedenle genellikle birleştirilir invalidate().
invalidate();
requestLayout();
Bunun bir örneği, özel bir etiketin text özelliği değiştiğinde verilebilir. Etiketin boyutu değişecek ve bu nedenle yeniden ölçülüp yeniden çizilmesi gerekiyor.
forceLayout()Bir requestLayout()üst görünüm grubunda çağrılan bir varsa, alt görünümlerini yeniden ölçmek ve yaymak gerekmez. Bununla birlikte, bir çocuğun yeniden ölçüme ve röleye dahil edilmesi gerekiyorsa forceLayout(), çocuğu arayabilirsiniz . forceLayout()yalnızca requestLayout()doğrudan ebeveynindeki bir a ile birlikte ortaya çıkarsa çocuk üzerinde çalışır . Tek forceLayout()başına arama yapmanın bir etkisi olmayacaktır, çünkü requestLayout()görünüm ağacını tetiklemez .
İle ilgili daha ayrıntılı açıklama için bu Soru ve Cevapları okuyun forceLayout().
View kaynak kodurequestLayout()önce arayabilirsiniz invalidate(). İkisi de hemen bir düzen veya çizim yapmaz. Aksine, sonunda bir geçiş ve yeniden çizim ile sonuçlanacak bayrakları ayarlarlar.
Burada bazı yanıtlar bulabilirsiniz: http://developer.android.com/guide/topics/ui/how-android-draws.html
Benim için invalidate()yalnızca görünümü yenilerken, görünümü requestLayout()yenileyip ekranda görünümün boyutunu hesaplamak için yapılan bir çağrı .
yeniden çizmek istediğiniz bir görünümde invalidate () yöntemini kullanırsanız, onDraw öğesinin (Canvas c) çağrılmasını sağlar ve requestLayout () tüm düzen oluşturmayı (ölçüm aşaması ve konumlandırma aşaması) yeniden çalıştırır. Çalışma zamanındaki çocuk görünümünün boyutunu değiştiriyorsanız, ancak yalnızca üst görünümdeki kısıtlamalar gibi belirli durumlarda kullanmalısınız (yani, ebeveyn yüksekliğinin veya genişliğinin WRAP_CONTENT olduğu anlamına gelir ve bu nedenle eşleşme, çocukları tekrar sarmadan önce ölçün)
Bu cevap hakkında doğru değilforceLayout() .
Eğer görebileceğiniz gibi kodforceLayout() "Bir relayout gerekiyor" ama ne zamanlamayı ne de tetiği o relayout yaptığı gibi bu sadece işaretleri görünümü. Geçiş, gelecekte bir noktada görünümün ebeveyninin başka bir nedenden ötürü ortaya konmasına kadar gerçekleşmeyecektir.
forceLayout()Ve kullanırken çok daha büyük bir sorun var requestLayout():
Diyelim ki forceLayout()bir görünümü çağırdınız . Şimdi requestLayout()bu görünümün bir soyundan çağrı yaparken , Android requestLayout()bu soyun atalarını tekrar tekrar çağırır . Sorun, aradığınız görünümde özyinelemeyi durduracağıdır forceLayout().Böylece requestLayout()çağrı hiçbir zaman görünüm köküne ulaşmaz ve böylece bir düzen geçişi asla planlanmaz. Görünüm hiyerarşisinin tüm alt ağacı bir düzen bekliyor ve requestLayout()bu alt ağacın herhangi bir görünümünü çağırmak bir düzene neden olmaz. Yalnızca requestLayout()bu alt ağacın dışındaki herhangi bir görünümü çağırmak büyüyü bozar.
Ben uygulanmasını forceLayout()(ve requestLayout()kırılmasını nasıl etkilediğini düşünürdüm ve kodunuzda bu işlevi asla kullanmamalısınız.
Viewve konuyu kendim çalıştırarak ve hata ayıklayarak anladım.
forceLayout()API'nin amacını merak ediyorum : aslında bir düzen geçişini zorlamıyor, sadece gözlemlenenonMeasure() bir bayrağı değiştiriyor , ancak açık bir şekilde onMeasure()çağrılmadığı sürece çağrılmayacak. Bu, bununla eşleştirilmesi gerektiği anlamına gelir . Öte yandan, hala yapmam gerekiyorsa neden performans göstermeliyim ? requestLayout()View#measure()forceLayout()requestLayout()forceLayout()requestLayout()
requestLayout()herşeyi forceLayout()de yapar.
forceLayoutmantıklı. Sonunda sadece çok kötü bir şekilde adlandırılmış ve belgelenmiştir.
invalidate()---> onDraw()UI iş parçacığından
postInvalidate()---> onDraw()arka plan iş parçacığından
requestLayout()---> onMeasure()ve onLayout()VE DEĞİL Mutlaka onDraw()
forceLayout()---> onMeasure()ve onLayout() SADECE doğrudan ebeveyn çağırırsa requestLayout().