Должен ли я вызвать 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метода , потому что mixinс на 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-условия оцениваются только в режиме отладки , это не имеет значения, когда вы создаете свое приложение, то есть в производственном режиме.


Далее я расскажу вам, что 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 где-то в своем собственном методе, вы не потеряете никакой ценности без добавления дополнительных функций в миксины.

creativecreatorormaybenot
источник
1
Флаттер официальные документы не очень хороши :( спасибо за ваш ответ :)
CopsOnRoad
Спасибо за ваше объяснение, не могли бы вы объяснить, что в initState()методе есть только одна строка assert(...), так в чем же преимущество вызова даже super.initState()в производственном приложении?
CopsOnRoad
1
Большое спасибо. Теперь это имеет смысл! Так что я думаю быть на более безопасной стороне, и ради хорошей практики программирования хорошо держать это в начале кода.
К
@creativecreatorormaybenot Это означает, что команда Flutter сошла с ума, применяя этот mustCallSuperметод уже более 2 лет с момента появления Flutter. Какая польза от этого, сэр?
CopsOnRoad
@creativecreatorormaybenot Даже если команда создала его mixin, все еще там будет одно утверждение в этом , initStateкоторый assert(...), таким образом , что это значение даже вызова super.initState()для производства приложение?
CopsOnRoad
3

super.initState()всегда должна быть первой строкой в ​​вашем initStateметоде.

Из документов:

initState (): если вы переопределите это, убедитесь, что ваш метод начинается с вызова super.initState ().

CopsOnRoad
источник
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 перед тем, как избавиться от других вещей, компоненты, зависящие от вашего базового класса, могут конфликтовать.
Анирудх Шарма