The build Metode ini dirancang sedemikian rupa bahwa itu harus murni / tanpa efek samping . Ini karena banyak faktor eksternal dapat memicu pembangunan widget baru, seperti:
- Rute pop / push
- Ubah ukuran layar, biasanya karena tampilan keyboard atau perubahan orientasi
- Widget induk menciptakan ulang anaknya
- Widget InheritedWidget tergantung pada
Class.of(context)
perubahan ( pola)
Ini berarti bahwa build
metode ini tidak boleh memicu panggilan http atau memodifikasi keadaan apa pun .
Bagaimana ini terkait dengan pertanyaan?
Masalah yang Anda hadapi adalah bahwa metode build Anda memiliki efek samping / tidak murni, membuat panggilan build tambahan merepotkan.
Alih-alih mencegah panggilan build, Anda harus membuat metode build Anda murni, sehingga dapat dipanggil kapan saja tanpa dampak.
Dalam kasus contoh Anda, Anda akan mengubah widget Anda menjadi StatefulWidget
kemudian ekstrak bahwa panggilan HTTP ke initState
dari Anda 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
},
);
}
}
Saya sudah tahu ini. Saya datang ke sini karena saya benar - benar ingin mengoptimalkan pembangunan kembali
Dimungkinkan juga untuk membuat widget yang mampu membangun kembali tanpa memaksa anak-anaknya untuk membangun juga.
Ketika instance widget tetap sama; Flutter dengan sengaja tidak akan membangun kembali anak-anak. Ini menyiratkan bahwa Anda dapat melakukan cache bagian pohon widget Anda untuk mencegah pembangunan kembali yang tidak perlu.
Cara termudah adalah dengan menggunakan const
konstruktor panah :
@override
Widget build(BuildContext context) {
return const DecoratedBox(
decoration: BoxDecoration(),
child: Text("Hello World"),
);
}
Berkat const
kata kunci itu, instance dari DecoratedBox
akan tetap sama meskipun build disebut ratusan kali.
Tetapi Anda dapat mencapai hasil yang sama secara manual:
@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,
],
);
},
);
}
Dalam contoh ini ketika StreamBuilder diberitahu tentang nilai-nilai baru, subtree
tidak akan membangun kembali bahkan jika StreamBuilder / Kolom melakukannya. Itu terjadi karena, berkat penutupan, contoh MyWidget
tidak berubah.
Pola ini banyak digunakan dalam animasi. Kegunaan umum adalah AnimatedBuilder
dan semua transisi seperti AlignTransition
.
Anda juga dapat menyimpan subtree
ke bidang kelas Anda, meskipun kurang direkomendasikan karena merusak fitur hot-reload.