Haruskah saya menelepon super.initState di akhir atau di awal?

10

Saya bingung ke mana harus memanggil super.initSate()bergetar? Dalam beberapa contoh kode, ini disebut di awal dan yang lain di akhir. Apakah ada perbedaan?

Saya sudah mencoba google ini tetapi belum menemukan penjelasan tentang posisi pemanggilan fungsi ini.

Yang mana yang benar?

void initState() {
  super.initState();    
  //DO OTHER STUFF
}

atau

void initState() {    
  //DO OTHER STUFF
  super.initState();    
}
K Vij
sumber

Jawaban:

4

Itu penting untuk mixins (dan karena itu untuk Anda juga)

Ini adalah paradigma dalam kerangka Flutter untuk memanggil metode super ketika mengesampingkan metode siklus hidup dalam a State. Inilah sebabnya mengapa bahkan deactivatememiliki mustCallSuperanotasi .
Selain itu , beberapa orang mixinberharap Anda memanggil metode super dari metode siklus hidup tersebut pada titik tertentu dalam fungsi.

Ini berarti bahwa Anda harus mengikuti dokumentasi dan menelepon super.dispose di akhirdispose metode Anda karena mixins Statedalam kerangka berharap bahwa ini adalah masalahnya.
Misalnya: TickerProviderStateMixindanSingleTickerProviderStateMixin nyatakan super.dispose di akhir:

Semua Ticker harus [..] dibuang sebelum memanggil super.dispose ().

Contoh lain: AutomaticKeepAliveMixinjalankan logika diinitState dan dispose.

Kesimpulan

Mulailah initStatedengansuper.initState dan akhiri disposedengansuper.dispose jika Anda ingin menambahkan sisi yang mudah dan aman mixinke State.
Selanjutnya, ikuti dokumentasi untuk metode siklus hidup lainnya (metode apa pun yang Anda timpa State) karena kerangka kerja akan mengharapkan Anda memanggil metode super seperti yang dijelaskan dalam dokumentasi.

Jadi, berikut ini yang harus Anda lakukan:

void initState() {
  super.initState();    
  //DO OTHER STUFF
}

Namun, itu tidak terlalu penting State, yang akan saya jelaskan berikut ini dan bahkan untuk mixin, itu hanya masalah untuk pernyataan dari apa yang saya temukan - jadi itu tidak akan mempengaruhi aplikasi produksi Anda.

Itu tidak masalah untuk State

Saya pikir dua jawaban sebelumnya dari Pablo Barrera dan CopsOnRoad adalah menyesatkan karena kebenaran dari masalah ini adalah bahwa itu benar-benar tidak peduli dan Anda tidak perlu melihat jauh.

Satu-satunya tindakan yang super.initStatedan super.disposedilakukan dalam Statekelas itu sendiri adalah pernyataan dan karena - pernyataanassert hanya dievaluasi dalam mode debug , tidak masalah sama sekali setelah membangun aplikasi Anda, yaitu dalam mode produksi.


Berikut ini, saya akan memandu Anda melalui apa super.initStatedan super.disposelakukan di State, yang merupakan semua kode yang akan dieksekusi ketika Anda tidak memiliki mixin tambahan.

initState

Mari kita lihat kode apa yang dieksekusi super.initStateterlebih dahulu ( sumber ):

@protected
@mustCallSuper
void initState() {
  assert(_debugLifecycleState == _StateLifecycle.created);
}

Seperti yang Anda lihat, hanya ada pernyataan siklus hidup dan tujuannya adalah untuk memastikan widget Anda berfungsi dengan benar. Jadi selama Anda menelepon di super.initState suatu tempat di Anda sendiri initState, Anda akan melihat AssertionErrorjika widget Anda tidak berfungsi sebagaimana dimaksud. Tidak masalah jika Anda mengambil tindakan sebelumnya karena asserthanya dimaksudkan untuk melaporkan bahwa ada sesuatu dalam kode Anda yang salah dan Anda akan melihat bahwa bahkan jika Anda menelepon super.initStatedi akhir metode Anda.

dispose

The disposeMetode ini analog ( sumber ):

@protected
@mustCallSuper
void dispose() {
  assert(_debugLifecycleState == _StateLifecycle.ready);
  assert(() {
    _debugLifecycleState = _StateLifecycle.defunct;
    return true;
  }());
}

Seperti yang Anda lihat, itu juga hanya berisi pernyataan yang menangani pemeriksaan siklus hidup debug . Yang kedua di assertsini adalah trik yang bagus karena memastikan bahwa _debugLifecycleStatehanya diubah dalam mode debug (karena assert-Statement hanya dieksekusi dalam mode debug).
Ini berarti bahwa selama Anda memanggil super.dispose suatu tempat dalam metode Anda sendiri, Anda tidak akan kehilangan nilai apa pun tanpa mixin menambahkan fungsionalitas tambahan.

creativecreatorormaybenot
sumber
1
Flutter docs resmi tidak terlalu bagus :( terima kasih atas jawaban Anda :)
CopsOnRoad
Terima kasih atas penjelasan Anda, maukah Anda menjelaskan, hanya ada satu baris dalam initState()metode ini assert(...), jadi apa manfaatnya bahkan memanggil super.initState()aplikasi produksi?
CopsOnRoad
1
Terima kasih banyak. Sekarang masuk akal! Jadi saya kira berada di sisi yang lebih aman dan demi praktik pemrograman yang baik, ada baiknya untuk menyimpannya di awal kode.
K Vij
@creativecreatorormaybenot Itu berarti tim Flutter sudah tidak waras dengan memasukkan mustCallSupermetode itu selama lebih dari 2 tahun sekarang sejak Flutter muncul. Apa manfaatnya meletakkannya di sana, Tuan?
CopsOnRoad
@creativecreatorormaybenot Bahkan jika tim telah menciptakan untuk mixin, masih ada akan menjadi pernyataan tunggal dalam hal ini initStateyang assert(...), jadi apa pentingnya bahkan memanggil super.initState()untuk aplikasi produksi?
CopsOnRoad
3

super.initState()harus selalu menjadi baris pertama dalam initStatemetode Anda .

Dari dokumen:

initState (): Jika Anda menimpa ini, pastikan metode Anda dimulai dengan panggilan ke super.initState ().

CopsOnRoad
sumber
2

Seperti yang bisa Anda lihat di kelas dari framework, Anda harus melakukan segalanya setelah widget diinisialisasi, artinya setelah super.initState().

Saya kasus membuang akan secara logis dengan cara lain, pertama lakukan semuanya dan kemudian telepon super.dispose().

@override
void initState() {
  super.initState();
  // DO STUFF
}

@override
void dispose() {
  // DO STUFF
  super.dispose();
}
Pablo Barrera
sumber
Terima kasih. Tetapi saya perhatikan bahwa dalam beberapa contoh kode. itu disebut di akhir metode initState ...
K Vij
Itulah yang saya katakan
Pablo Barrera
0

initState dipanggil secara default setiap kali widget stateful baru ditambahkan ke pohon widget. Sekarang super.initState melakukan implementasi standar kelas dasar widget Anda. Jika Anda memanggil sesuatu sebelum super.initState yang tergantung pada kelas dasar maka ini dapat menyebabkan masalah. Karena itu disarankan agar Anda memanggil initState dengan cara ini:

@override
void initState() {
  super.initState();
  // DO STUFF
}
Anirudh Sharma
sumber
Alasannya agak cacat karena untuk disposeitu adalah sebaliknya. Kerangka kerja mengharapkan Anda untuk menelepon super.dispose di akhir , tetapi rekomendasi itu benar.
creativecreatorormaybenot
Karena jika Anda memanggil super.dispose sebelum membuang hal-hal lain maka komponen yang tergantung pada kelas dasar Anda mungkin berbenturan.
Anirudh Sharma