İnşa yöntemi olması gerektiği şekilde tasarlanmıştır yan etkiler olmaksızın / saf . Bunun nedeni, birçok dış faktörün yeni bir pencere öğesi derlemesini tetikleyebilmesidir, örneğin:
- Yönlendirme / itme
- Genellikle klavye görünümü veya yön değişikliği nedeniyle ekranı yeniden boyutlandırma
- Üst widget altını yeniden oluşturdu
- Widget'ın (
Class.of(context)
desen) değişikliğine bağlı olduğu bir InheritedWidget
Bu demektir ki build
bir yöntem olmalıdır olmayan bir http çağrısı tetikleyecek veya durumunu değiştirmek .
Bunun soruyla nasıl bir ilişkisi var?
Karşılaştığınız sorun, oluşturma yönteminizin yan etkilere sahip olması / saf olmaması ve gereksiz derleme çağrısını zahmetli hale getirmesidir.
Derleme çağrısını önlemek yerine, derleme yönteminizi saf hale getirmelisiniz, böylece herhangi bir anda etki olmadan çağrılabilir.
Senin örnek durumda, bir widget'ınızı dönüştürmek istiyorum StatefulWidget
sonra bu HTTP çağrısı ayıklamak initState
, aramalarınızdan State
:
class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
Future<int> future;
@override
void initState() {
future = Future.value(42);
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: future,
builder: (context, snapshot) {
// create some layout here
},
);
}
}
Bunu zaten biliyorum. Buraya geldim çünkü yeniden inşaları gerçekten optimize etmek istiyorum
Çocuklarını da oluşturmaya zorlamadan yeniden inşa edebilen bir widget yapmak da mümkündür.
Bir widget örneği aynı kaldığında; Flutter kasıtlı olarak çocukları yeniden inşa etmez. Gereksiz yeniden oluşturmaları önlemek için pencere öğesi ağacınızın bölümlerini önbelleğe alabileceğiniz anlamına gelir.
En kolay yol, dart const
oluşturucularını kullanmaktır :
@override
Widget build(BuildContext context) {
return const DecoratedBox(
decoration: BoxDecoration(),
child: Text("Hello World"),
);
}
Bu const
anahtar kelime sayesinde , DecoratedBox
derleme yüzlerce kez çağrılsa bile örneği aynı kalacaktır.
Ancak aynı sonucu manuel olarak da elde edebilirsiniz:
@override
Widget build(BuildContext context) {
final subtree = MyWidget(
child: Text("Hello World")
);
return StreamBuilder<String>(
stream: stream,
initialData: "Foo",
builder: (context, snapshot) {
return Column(
children: <Widget>[
Text(snapshot.data),
subtree,
],
);
},
);
}
Bu örnekte, StreamBuilder yeni değerler konusunda bilgilendirildiğinde subtree
, StreamBuilder / Column yapsa bile yeniden oluşturulmayacaktır. Bunun nedeni, kapanış sayesinde, örneğinin MyWidget
değişmemesidir.
Bu kalıp, animasyonlarda çok kullanılır. Tipik kullanımları AnimatedBuilder
ve gibi tüm geçişler AlignTransition
.
subtree
Çalışırken yeniden yükleme özelliğini bozduğu için daha az tavsiye edilmesine rağmen, sınıfınızın bir alanına da depolayabilirsiniz .