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 buildmetode 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 StatefulWidgetkemudian ekstrak bahwa panggilan HTTP ke initStatedari 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 constkonstruktor panah :
@override
Widget build(BuildContext context) {
return const DecoratedBox(
decoration: BoxDecoration(),
child: Text("Hello World"),
);
}
Berkat constkata kunci itu, instance dari DecoratedBoxakan 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, subtreetidak akan membangun kembali bahkan jika StreamBuilder / Kolom melakukannya. Itu terjadi karena, berkat penutupan, contoh MyWidgettidak berubah.
Pola ini banyak digunakan dalam animasi. Kegunaan umum adalah AnimatedBuilderdan semua transisi seperti AlignTransition.
Anda juga dapat menyimpan subtreeke bidang kelas Anda, meskipun kurang direkomendasikan karena merusak fitur hot-reload.