Хроники управления состоянием Flutter 4

Итак, сегодня я хотел написать об унаследованных виджетах, но понял, что концепция подъема состояния и обратных вызовов может иметь жизненно важное значение для лучшего понимания и создания надлежащих основ для унаследованных виджетов, поэтому я начну с этого.

Управление состоянием довольно интересно, оно делает наш код более живым и более реактивным.

Однако управление состоянием с помощью виджетов с отслеживанием состояния и ловушек флаттера имеет дело с локальными состояниями немного больше; где состояние или информация, которая изменяется, привязаны только к одному виджету и не являются полезными (не нужны) где-либо еще, поэтому изменения этого состояния влияют только на перестройку только того виджета, к которому они привязаны.

Но что, если нам нужно иметь состояние, от которого зависит более одного виджета? Что, если нам нужно состояние, которое при изменении запускает перестройку всех зависимых от него виджетов?

Допустим, например, что у нас есть виджет BlueSquare, который отображает количество нажатий на него, как показано ниже.

где каждый щелчок по квадрату автоматически обновляет отображаемый текст с обновленным общим количеством щелчков по этому квадрату. Допустим, мы хотели иметь набор BlueSquares, чтобы при щелчке по любому из них все blueSquares в этом наборе отображали накопленное количество кликов, сделанных пользователем.

Это означает, что количество щелчков - это не больше состояние, которое является локальным только для одного объекта blueSquare, но и состояние, от которого зависят многие другие объекты, а также может управляться более чем одним.

Итак, как нам это сделать?

Во флаттере у нас есть концепция подъема состояния, которая подразумевает, что мы берем то состояние, которое зависит от набора виджетов, и помещаем его до родительского виджета, который включает все эти виджеты, так что вы можете передать вниз это состояние для всех виджетов, которые в нем нуждаются (это похоже на концепцию бурения опоры для тех, кто приходит из React).

Модификация нашего виджета BlueSquare для принятия состояния «детализации» делает виджет немного менее сложным, и он не обязательно должен быть виджетом с отслеживанием состояния (поскольку нет собственного локального состояния, которым можно было бы управлять).

Затем мы перемещаем состояние кликов в родительский виджет, который автоматически должен иметь состояние, поскольку он будет управлять состоянием.

Пока это выглядит неплохо, у всех наших BlueSquare есть общий источник достоверной информации о количестве кликов, и это потрясающе. Но, попробовав код, очевидно, что, касаясь любого из объектов blueSquare, мы не наблюдаем никаких изменений.

Посмотрев также на код, мы замечаем, что функции ontap каждого из этих объектов blueSquare не имеют функциональности, и мы не можем просто пойти и добавить к нему установленное состояние, поскольку теперь это виджет без состояния.

На самом деле то, что мы ищем, - это способ иметь возможность общаться и передавать информацию родительскому виджету, когда появляется новая информация (например, касание; которое должно обновлять количество касаний), который будет интересно родителю.

Итак, как теперь гарантировать, что щелчок по каждому из объектов blueSquare обновляет состояние щелчков и запускает перестройку всех остальных объектов blueSquare?

Проще говоря, как мы можем передать информацию родительскому виджету?

Мы используем функции обратного вызова, да функции обратного вызова

Здесь мы создаем функцию в родительском виджете и передаем эту функцию в качестве параметра дочерним виджетам, эти функции используют ее параметры как средство ввода информации. Или при обратном вызове из дочернего виджета он выполняет код, определенный в нем, в области родительского виджета и может иметь доступ и управление переменными, параметрами и состоянием в родительском виджете.

Итак, по сути, мы создали функцию в основном родительском виджете, которая содержит все наши виджеты BlueSquare, функция определена для обновления значения переменной clicks внутри метода setState, чтобы она могла запускать перестройку родительского класса, а затем и все его дочерние виджеты, которые загрязнены.

Мы передали функции в качестве параметра всем функциям BlueSquare, и, как они используются в виджете BlueSquare, они находятся внутри функции onTap, ожидая, пока пользователь коснется их, чтобы вызвать.

Это работает отлично и помогает нам справляться с ситуациями, такими как наша, когда родительский виджет содержит данные, от которых зависят и изменяют несколько его дочерних виджетов, что зависит от их макета и, следовательно, от перестройки.

Как мы видели, существует довольно сильная связь между виджетами, пытающимися добиться нелокализованного управления состоянием таким способом, когда, например, что-то случится в будущем, и нам не нужен объект BlueSquare для отображения количества кликов, и нам нужно изменить Виджет BlueSquare, нам также нужно будет изменить реализацию родительского виджета, и это может оказаться утомительной работой, если у нас будет какое-то сложное состояние и несколько уровней в большом проекте.

Также

мы можем видеть, что начинается слишком много бурения, где, допустим, у нас был виджет внутри виджета BlueSquare, который также должен изменять и получать доступ к количеству кликов, и если это происходит, то иногда некоторым промежуточным виджетам может не потребоваться значение кликов , но если дочерний виджет это делает, нам нужно будет детализировать значение clicks до промежуточного значения (даже если оно ему не нужно), пока мы не дойдем до виджета, который действительно в нем нуждается. Это становится проблемой.

В нашей следующей статье мы рассмотрим, как решить такую ​​проблему с унаследованными виджетами.