Чи варто закликати super.initState наприкінці чи на початку?


10

Я розгублений, куди зателефонувати super.initSate()? У деяких прикладах коду він називається на початку, а в інших в кінці. Чи є різниця?

Я спробував перейти в Google, але не знайшов пояснення щодо позиції цього виклику функції.

Який з них правильний?

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

або

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

Відповіді:


4

Це має значення для mixins (і через це також для вас )

Це парадигма , в рамках Flutter для виклику методу супер при перевизначенні методів життєвого циклу в State. Ось чому навіть deactivateє mustCallSuperанотація .
Крім того , деякі mixinочікують, що ви викличете супер методи цих методів життєвого циклу в певний момент функції.

Це означає, що вам слід дотримуватися документації та зателефонувати super.dispose в кінці свого disposeметоду, оскільки mixins Stateу рамках очікують, що це так.
Наприклад: TickerProviderStateMixinі стверджувати в кінці:SingleTickerProviderStateMixin super.dispose

Перед тим, як зателефонувати на super.dispose (), потрібно видалити усі [..].

Ще один приклад: AutomaticKeepAliveMixinвиконує логіку в initStateі dispose.

Висновок

Почніть свій initStateзsuper.initState і закінчити ваш disposeзsuper.dispose , якщо ви хочете бути на легкій і безпечної стороні додавання mixinS до вашого State.
Крім того, слідкуйте за документацією щодо інших методів життєвого циклу (будь-який метод, який ви перезаписуєте State), оскільки рамки очікують, що ви викличете супер методи, як описано в документації.

Таким чином, наступне - що ви повинні зробити:

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

Однак це не має особливого значення State, про що я поясню в наступному, і навіть для комбінацій, це має значення лише для тверджень, судячи з того, що я міг би знайти - так це не вплине на ваше виробництво.

Це не має значення State

Я думаю, що попередні два відповіді від Пабло Баррери та CopsOnRoad вводять в оману, оскільки правда в тому, що це насправді не має значення і не потрібно шукати далеко.

Єдині діями , які super.initStateі super.disposeприймають в Stateкласі самі по собі є твердженнями і так assert-statements оцінюються тільки в режимі налагодження , це не має значення один раз побудувати ваше додаток, тобто в режимі виробництва.


Далі я проводжу вас через те, що робити super.initStateі що super.disposeробити State, який є весь код, який буде виконуватися, коли у вас немає додаткових комбінацій.

initState

Давайте розглянемо, який саме код виконується в super.initStateпершому ( джерело ):

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

Як бачите, існує лише твердження життєвого циклу, і його мета - забезпечити правильність роботи вашого віджета. Тому поки ви подзвоните super.initState десь у себе initState, ви побачите, AssertionErrorчи ваш віджет працює не за призначенням. Не має значення, чи вживали ви попередніх дій, оскільки це assertозначає лише повідомити, що щось у вашому коді все одно не так, і ви побачите це, навіть якщо ви зателефонуєте super.initStateв самому кінці свого методу.

dispose

disposeМетод аналогічний ( джерело ):

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

Як бачите, він також містить лише твердження, які обробляють перевірку життєвого циклу налагодження . Другий assertтут приємний трюк, оскільки він гарантує, що _debugLifecycleStateзмінено значення лише в режимі налагодження (оскільки- assertзаяви виконуються лише в режимі налагодження).
Це означає, що доки ви зателефонуєте super.dispose десь у своєму власному методі, ви не втратите жодної цінності без того, щоб міксинг додав додаткову функціональність.


1
Офіційні документи
Flutter

Дякуємо за ваше пояснення, ви також не хотіли б пояснити, що в initState()методі є лише один рядок assert(...), тож яка користь навіть від виклику super.initState()у виробничому додатку?
CopsOnRoad

1
Thx багато. Тепер це має сенс! Тож я маю на увазі більш безпечну сторону, і заради гарної практики програмування добре зберігати це на початку коду.
K Vij

@creativecreatorormaybenot Це означає, що команда Flutter вийшла з розуму, застосовуючи mustCallSuperцей метод вже більше 2 років з моменту появи Flutter . Яка користь розмістити його там, сер?
CopsOnRoad

@creativecreatorormaybenot Навіть якщо команда створила його mixin, все ще там буде одне твердження в цьому , initStateякий assert(...), таким чином , що це значення навіть виклику super.initState()для виробництва додаток?
CopsOnRoad

3

super.initState()завжди повинен бути першим рядком у вашому initStateметоді.

З документів:

initState (): Якщо ви скасуєте це, переконайтеся, що ваш метод починається з виклику до super.initState ().


2

Як ви могли бачити в класах з фреймворку, ви повинні робити все після ініціалізації віджета, тобто після super.initState().

У випадку розпорядження було б логічно інакше, спочатку зробіть усе, а потім зателефонуйте super.dispose().

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

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

Дякую. Але я помітив, що в деяких прикладах коду. Він називається в кінці методу initState ...
K Vij

Ось що я сказав
Пабло Баррера

0

initState викликається за замовчуванням кожного разу, коли новий новий віджет додається у дерево віджетів. Тепер super.initState виконує реалізацію за замовчуванням базового класу вашого віджета. Якщо ви зателефонуєте перед тим, як super.initState залежить від базового класу, це може спричинити проблеми. Ось чому рекомендується викликати initState таким чином:

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

Міркування дещо хибні, оскільки для disposeнього навпаки. Рамка очікує, що ви зателефонуєте super.dispose в кінці , але рекомендація правильна.
creativecreatorormaybenot

Тому що якщо ви подзвоните super.dispose перед тим, як розпоряджатися іншими речами, то компоненти, які залежать від вашого базового класу, можуть зіткнутися.
Аніруд Шарма
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.