TL; DR
UpdateShouldNotify yöntemi içinde yoğun hesaplama kullanmayın ve bir pencere öğesi oluştururken yeni yerine const kullanın
Öncelikle Widget, Element ve Render nesnelerinin ne olduğunu anlamalıyız.
- Render nesneleri, gerçekte ekranda gösterilen nesnelerdir. Bunlar değişken , resim ve düzen mantığı içerir. Oluşturma ağacı, web'deki Belge Nesne Modeline (DOM) çok benzer ve bir işleme nesnesine bu ağaçta bir DOM düğümü olarak bakabilirsiniz.
- Widget - işlenmesi gereken şeyin bir açıklamasıdır. Bunlar değişmez ve ucuz. Öyleyse, bir Widget "Ne?" (Bildirime dayalı yaklaşım) sorusunu yanıtlarsa, bir Render nesnesi "Nasıl?" (Zorunlu yaklaşım) sorusuna yanıt verir. Web'den bir benzetme "Sanal DOM" dur.
- Element / BuildContext - Widget ve Render nesneleri arasında bir proxy'dir . Ağaçta * bir widget'in konumu ve karşılık gelen bir widget değiştirildiğinde Render nesnesinin nasıl güncelleneceği hakkında bilgiler içerir.
Şimdi InheritedWidget ve BuildContext'in inheritFromWidgetOfExactType yöntemine dalmaya hazırız .
Örnek olarak, Flutter'ın InheritedWidget ile ilgili belgelerinden bu örneği dikkate almamızı tavsiye ederim:
class FrogColor extends InheritedWidget {
const FrogColor({
Key key,
@required this.color,
@required Widget child,
}) : assert(color != null),
assert(child != null),
super(key: key, child: child);
final Color color;
static FrogColor of(BuildContext context) {
return context.inheritFromWidgetOfExactType(FrogColor);
}
@override
bool updateShouldNotify(FrogColor old) {
return color != old.color;
}
}
InheritedWidget - sadece bizim durumumuzda önemli bir yöntemi uygulayan bir widget - updateShouldNotify .
updateShouldNotify - bir parametre oldWidget'i kabul eden ve bir boole değeri döndüren bir işlev : true veya false.
Herhangi bir widget gibi, InheritedWidget'in de karşılık gelen bir Element nesnesi vardır. Öyle InheritedElement . InheritedElement , her yeni pencere öğesi oluşturduğumuzda pencere öğesinde updateShouldNotify çağrısı yapar ( bir ataya setState'i çağırın ). Ne zaman updateShouldNotify döndürür true aracılığıyla InheritedElement yineler bağımlılıkları (?) Ve çağrı yöntemi didChangeDependencies üzerinde.
InheritedElement bağımlılıkları nereden alır ? Burada inheritFromWidgetOfExactType yöntemine bakmalıyız .
mirasFromWidgetOfExactType - BuildContext'te tanımlanan bu yöntem ve
her Element BuildContext arabirimini (Element == BuildContext) uygular. Yani her Element bu yönteme sahiptir.
HeritageFromWidgetOfExactType koduna bakalım:
final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[targetType];
if (ancestor != null) {
assert(ancestor is InheritedElement);
return inheritFromElement(ancestor, aspect: aspect);
}
Burada, türe göre eşlenen _inheritedWidgets içinde bir ata bulmaya çalışıyoruz . Eğer ata bulunursa, o zaman inheritFromElement'i çağırırız .
İnheritFromElement kodu :
InheritedWidget inheritFromElement(InheritedElement ancestor, { Object aspect }) {
assert(ancestor != null);
_dependencies ??= HashSet<InheritedElement>();
_dependencies.add(ancestor);
ancestor.updateDependencies(this, aspect);
return ancestor.widget;
}
- Mevcut elemanın (_dependencies.add (ancestor)) bağımlılığı olarak atayı ekliyoruz
- Mevcut öğeyi atanın bağımlılıklarına ekliyoruz (ancestor.updateDependencies (this, angle))
- MirasFromWidgetOfExactType (ancestor.widget döndür ) sonucunda atanın parçacığını döndürürüz
Artık InheritedElement'in bağımlılıklarını nereden aldığını biliyoruz.
Şimdi didChangeDependencies yöntemine bakalım . Her Eleman bu yönteme sahiptir:
void didChangeDependencies() {
assert(_active);
assert(_debugCheckOwnerBuildTargetExists('didChangeDependencies'));
markNeedsBuild();
}
Gördüğümüz gibi, bu yöntem yalnızca bir öğeyi kirli olarak işaretler ve bu öğenin bir sonraki çerçevede yeniden oluşturulması gerekir. Yeniden oluşturma , karşılık gelen bileşen öğesinde çağrı yöntemi oluşturma anlamına gelir .
Peki ya "InheritedWidget'ı yeniden oluşturduğumda tüm alt ağaç yeniden oluşturuluyor?" Burada Widget'ların değişmez olduğunu ve yeni widget oluşturursanız Flutter'ın alt ağacı yeniden oluşturacağını hatırlamalıyız. Nasıl düzeltebiliriz?
- Widget'ları elinizle önbelleğe alın (manuel olarak)
- Const kullanın çünkü const , değer / sınıfın tek bir örneğini oluşturur