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


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 ().


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.