stateful widget flutter передача параметров

Stateful widget flutter передача параметров

Класс StatefulWidget предназначен для создания виджетов, которые хранят состояние. При этом несмотря на то, что объекты класса StatefulWidget являются неизменяемыми (immutable), их состояние является изменяемым (mutable).

Например, определим простейший виджет StatefulWidget:

Итак,здесь определен класс Counter, который наследуется от StatefulWidget.

Затем виджет Counter встравивается в приложение в элемент Scaffold:

В итоге при запуске приложения мы увидим текст со значением переменной value

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

Но ключевая идея StatefulWidget состоит в том, что мы можем менять его состояние. Поэтому добавим изменение переменной value по нажатию на кнопку:

В итоге по нажатию на кнопку увеличится значение переменной value:

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

Передача данных в State

При необходимости в объект State можно передавать данные извне. В этом случае передача осуществляется через StatefulWidget. Например, изменим выше приведенный пример таким образом, чтобы State принимал начальные данные извне:

При создании объекта State виджет Counter передает в конструктор соответствующие данные:

При этом эти значения виджет Counter сам принимает извне с помощью своего конструктора:

В итоге при применении виджета мы можем передавать в него различные данные:

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

Получение виджета

С помощью свойства widget внутри State можно обращаться к виджету StatefulWidget, к которому привязан объект State:

Вынос логики изменения состояния в метод

Если метод, в который вынесены все действия, ничего не возвращает и не принимает никаких параметров, то есть соответствует определению onPressed (как в данном случае), то можно напрямую присвоить функцию параметру onPressed:

Источник

Андрей Алеев

Flutter: Stateful и Stateless виджеты

Поскольку Flutter декларативный, пользовательский интерфейс строится как некоторая функция от состояния

UI = f(state)

Другими словами, UI наблюдает за State-ом.
Будучи Android Java и Kotlin разработчиком, я привык писать все в императивном стиле. Например,

С другой стороны, во Flutter, если вы хотите поменять UI, сначала Вам нужно поменять State

State может быть определено как “whatever data you need in order to rebuild your UI at any moment in time”

Stateful и stateless виджеты

Вкратце, Stateful — это аналог var, а stateless — это аналог val переменных в Koltin.
Нельзя поменять состояние StatelessWidget. Его следует использовать в случае, когда UI элемент создается единожды и его состояние не будет меняться. Например, статичный текст, иконки, изображения и т.п..

Stateful виджеты могут меняться в рантайме. Это может быть поле для ввода текста, слайдер, чекбокс и т.п.
Состояние widget’s храниться в объекте State. Когда состояние виджета меняется, этот объект вызывает setState(), сообщая фреймворку о необходимости перерисовать виджет.

Чтобы объявить StatefulWidget необходимо унаследовать StatefulWidget, а также создать State для него

Ephemeral state и App state

Начнем с Application state. Этот тип состояния используется когда есть необходимость шарить данные между компонентами приложения: экранами, виджетами или даже сессиями. В этом типе данным вы вероятно захотите хранить, например, пользовательские настройки, корзину покупателя или список элементов, загруженный с сервера.

Ephemeral state — временное состояние — состояние вью, которое может поменяться. Например, текущая страница в PageView, текущий прогресс в ProgressBar или выбранная radioButton в radioGroup

Источник

Управление состоянием в приложениях на Flutter

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

Общие принципы

Flutter — реактивный фреймворк, и для разработчика, специализирующегося на нативной разработке, его философия может быть непривычна. Поэтому начнём с небольшого обзора.

Пользовательский интерфейс на Flutter, как и в большинстве современных фреймворков, состоит из дерева компонентов (виджетов). При изменении какого-либо компонента, происходит перерендеринг этого и всех его дочерних компонентов (с внутренними оптимизациями, о которых ниже). При глобальном изменении отображения (например, повороте экрана), перерисовывается всё дерево виджетов.

Этот подход может показаться неэффективным, но на самом деле он передаёт программисту контроль за скоростью работы. Если производить обновление интерфейса на самом верхнем уровне без необходимости — всё будет работать медленно, но при правильной компоновке виджетов, приложения на Flutter могут быть очень быстрыми.

Во Flutter существует два типа виджетов — Stateless и Stateful. Первые (аналог Pure Components в React) не имеют состояния и полностью описываются своими параметрами. Если не меняются условия отображения (скажем, размер области, в которой должен показываться виджет) и его параметры, система переиспользует ранее созданное визуальное представление виджета, поэтому использование Stateless виджетов хорошо сказывается на производительности. При этом всё равно при каждой перерисовке виджета формально создаётся новый объект и запускается конструктор.

Stateful виджеты сохраняют некоторое состояние между рендерингами. Для этого они описываются двумя классами. Первый из классов, собственно виджет, описывает объекты, которые создаются при каждой отрисовке. Второй класс, описывает состояние виджета и его объекты передаются в создаваемые объекты виджета. Изменение состояния Stateful виджетов является основным источником перерисовки интерфейсов. Для этого нужно изменить его свойства внутри вызова метода SetState. Таким образом, в отличие от многих других фреймворков, во Flutter нет неявного отслеживания состояния — любое изменение свойств виджета вне метода SetState не приводит к перерисовке интерфейса.

Теперь, после описания основ, можно начать с простого приложения, использующего Stateless и Stateful виджеты:

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

Если нужны более живучие состояния

Идём дальше. Состояние Stateful виджетов сохраняется между перерисовками интерфейсов, но только до тех пор, пока виджет нужен, т.е. реально находится на экране. Проведём простой эксперимент — разместим наш список на вкладке:

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

При запуске можно увидеть, что при переключении между вкладками, состояние удаляется (вызывается метод dispose()), при возврате создаётся снова (метод initState()). Это разумно, так как хранение состояния неотображаемых виджетов будет отнимать ресурсы системы. В том случае, когда состояние виджета должно переживать его полное скрытие, возможны несколько подходов:

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

Мне больше нравится этот подход, т.к. он позволяет изолировать бизнес-логику от пользовательского интерфейса. Это особенно актуально в связи с тем, что Flutter Release Preview 2 добавил возможность создавать pixel-perfect интерфейсы для iOS, но делать это нужно, разумеется, на соответствующих виджетах.

Во-вторых, можно использовать знакомый программистам React подход поднятия состояния, когда данные хранятся в компонентах, расположенных выше по дереву. Поскольку Flutter перерисовывает интерфейс только при вызове метода setState(), эти данные можно менять и использовать без рендеринга. Такой подход несколько более сложен и повышает связность виджетов в структуре, но позволяет точечно задавать уровень хранения данных.

Наконец существуют библиотеки хранения состояния, например flutter_redux.

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

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

Сохранение позиции скролла

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

Обратите внимание на виджеты ScrollController и NotificationListener (а также ранее использованный DefaultTabController). Концепция виджетов, не имеющих своего отображения должна быть знакома разработчикам, работающим с React/Redux — в этой связке активно используются компоненты-контейнеры. Во Flutter виджеты без отображения обычно используются для добавления функциональности к дочерним виджетам. Это позволяет оставить сами визуальные виджеты легковесными и не обрабатывать системные события там, где они не нужны.

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

Переживаем выключение приложения

Сохранение информации на время работы приложения — это хорошо, но часто хочется сохранять её и между сеансами, особенно учитывая привычку операционных систем закрывать фоновые приложения при нехватке памяти. Основные варианты постоянного хранения данных во Flutter это:

Для демонстрации сделаем сохранение состояния прокрутки в Shared preferences. Для этого добавим восстановление позиции скролла при инициализации состояния _MyHomePageState и сохранение при прокрутке.

Здесь нужно немного остановиться на асинхронной модели Flutter/Dart, поскольку все внешние службы работают на асинхронных вызовах. Принцип работы этой модели сходен с node.js — есть один основной поток выполнения (thread), который прерывается на асинхронные вызовы. На каждом следующем прерывании (а UI делает их постоянно) обрабатываются результаты завершённых асинхронных операций.При этом есть возможность запускать тяжеловесные вычисления в фоновых threads (через функцию compute).

Итак, запись и чтение в SharedPreferences делаются асинхронно (хотя библиотека позволяет синхронное чтение из кэша). Для начала разберёмся с чтением. Стандартный подход к асинхронному получению данных выглядит так — запустить асинхронный процесс, по его завершению выполнить SetState, записав полученные значения. В результате пользовательский интерфейс будет обновлён с использованием полученных данных. Однако в данном случае мы работаем не с данными, а с положением прокрутки. Нам не нужно обновлять интерфейс, нужно только вызвать метод jumpTo у ScrollController. Проблема в том, что результат обработки асинхронного запроса может вернуться в любой момент и совсем не обязательно будет что и куда прокручивать. Чтобы гарантированно выполнить операцию на полностью инициализированном интерфейсе, нам нужно … всё-таки выполнить прокрутку внутри setState.

Получаем примерно такой код:

С записью всё интереснее. Дело в том, что в процессе прокрутки, сообщающие об этом события приходят постоянно. Запуск асинхронной записи при каждом изменении значения может привести к ошибкам приложения. Нам нужно обрабатывать только последнее событие из цепочки. В терминах реактивного программирования это называется debounce и его мы и будем использовать. Dart поддерживает основные возможности реактивного программирования через потоки данных (stream), соответственно нам нужно будет создать поток из обновлений позиции прокрутки и подписаться на него, преобразуя его с помощью Debounce. Для преобразования нам потребуется библиотека stream_transform. В качестве альтернативного подхода, можно использовать RxDart и работать в терминах ReactiveX.

Источник

Урок 2. StatelessWidget и StatefulWidget

В предыдущем уроке мы рассмотрели пример построения интерфейса приложения с помощью виджетов, создали свой виджет MyBody наследуемый от класса StatelessWidget.

Все собственные классы-виджеты рекомендуется создавать от двух основных: StatelessWidget и StatefulWidget.

Отдельные части интерфейса удобно объединять в отдельные виджеты, созданные от этих двух суперклассов, но какой из них использовать – мы рассмотрим в этом уроке.

1. StatelessWidget

StatelessWidget – рекомендуется для неизменяемых виджетов. Это такие виджеты которые не имеют внутреннего состояния, зависят только от конфигурационных параметров и от родительских виджетов.

Вот некоторые виджеты которые наследуются от StatelessWidget:

Самая простая конструкция для создания виджета от суперкласса StatelessWidget:

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

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

Поскольку все данные для каждого блока нам известны заранее и не будут изменятся, то суперкласс StatelessWidget нам отлично подходит.

Создадим класс NewsBox от суперкласса StatelessWidget и определим в нем поля:
_title – заголовок анонса новости,
_text – содержание новостного сообщения,
_imageurl – ссылка на изображение.

Разберем строку final String _title;

title – поле нашего класса, переменная в которой мы будем хранить заголовок новостного сообщения

_ (подчеркивание перед именем переменной) – в языке Dart говорит о том что данная переменная скрыта и доступна только внутри объекта нашего класса (аналог private в других языках программирования)

String – наша переменная строкового типа

final – данная переменная должна быть объявлена при создании экземпляра класса и не может быть изменена

Можно было бы просто объявить поле в классе с помощью var title; в перспективе это плохой вариант:

Добавим конструктор в наш класс:

NewsBox – название конструктора должно совпадать с именем нашего класса.

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

В фигурных скобках <> указывается, что в конструкторе можно указать параметр imageurl со значением типа String.

Т.е. мы можем создать экземпляр нашего класса двумя способами:

А вот так вызывать наш конструктор нельзя:

Приведем краткую структуру, которую мы хотим вывести:

Листинг программы

В полном листинге программы мы усложнили функцию build чтобы получить ожидаемый результат:

Структура виджета NewsBox

Если задан параметр imageurl

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

Если параметр imageurl не задан

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

2. StatefulWidget

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

Под изменяемым состоянием понимается изменение внутреннего состояния экземпляра класса в зависимости от какого-то события (по нажатию, времени и пр.) Для этого нужно создавать виджет от суперкласса StatefulWidget.

Вот некоторые виджеты, которые наследуются от StatefulWidget:

Самая простая конструкция для создания виджета от суперкласса StatefulWidget:

Конструкция изменяемого виджета отличается от той которую мы использовали раньше:

Возьмем наш предыдущий виджет для отображения новостных анонсов и добавим в него кнопку «избранное» и счетчик который будет указывать сколько людей добавило новость в избранное. Т.е. у нас будет два состояния: «избранное» и «не избранное».

Поскольку изменяться будет только кнопка и счетчик, то мы и обернем их в отдельный виджет class NewsBoxFavourit extends StatefulWidget.

В нашем классе NewsBoxFavourit мы объявили два скрытых поля _num и _like, значение которых устанавливается через конструктор NewsBoxFavourit(this._num, this._like), после они передается в класс состояния «избранное» createState() => new NewsBoxFavouritState(_num, _like).

В классе состояния class NewsBoxFavouritState extends State мы объявили одноименные поля только тут они публичные и изменяемые.

Поля num и like в классе состояния можно сделать приватными, но мы так сделали намеренно, чтобы на момент изучения данного урока не было путаницы – какие из объявленных переменных мы используем для проверки и изменения (те которые публичные, в классе состояния).

Конструктор NewsBoxFavouritState(this.num, this.like) инициализирует переменные в классе.

Передать значения из виджета без конструктора можно с помощью переменной widget, для нашего примера: widget._num.

Так как переменные _num и _like в виджете NewsBoxFavourit не изменяемые, мы не можем использовать их напрямую, и должны переопределить в NewsBoxFavouritState таким образом:

setState() – в качестве параметра принимает функцию, в которой мы сделали смену состояния, после выполнения переданной функции setState вызывает перестроение виджета через функцию build() в классе состояния.

Еще функцию нашей кнопки можно было описать так:

Результат работы был бы таким же.

if(like) num++; else num—; – у нас сменилось состояние и теперь если мы добавили новость в избранное то количество точно увеличится на один, по этому мы прибавляем к счетчику единицу. И на оборот, если мы когда-то уже добавляли в избранное, а теперь убираем свой выбор – мы должны отнять единицу в переменной num.

В функции build класса NewsBoxFavouritState происходит вывод виджетов с учетом наших переменных num и like.

IconButton – виджет кнопки с иконкой, обязательные параметры icon и onPressed

size: 30.0 – через параметр size можно увеличить или уменьшить размер иконки

color: Colors.blue[500] – устанавливает оттенок синего цвета для иконки

onPressed: pressButton – вызов функции pressButton при нажатии на кнопку из нашего класса NewsBoxFavouritState

Структура виджета NewsBoxFavourit

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

Листинг программы

3. Итоги

StatelessWidget – нужен там где внутреннее состояние одно и оно сформировано параметрами и данными которые нам известны заранее.

StatefulWidget – нужен когда внутренних состояний больше одного и они могут сменять друг друга.

Виджеты от StatelessWidget и StatefulWidget могут включать друг друга.

Создатели Flutter SDK рекомендуют использовать StatelessWidget везде, где можно обойтись без StatefulWidget – связано это с тем что перестроение последнего стоит намного дороже. Так же рекомендуется сводить к миниму дочерних виджетов в StatefulWidget.

Источник

Passing data to StatefulWidget and accessing it in it’s state in Flutter

I have 2 screens in my Flutter app: a list of records and a screen for creating and editing records.

If I pass an object to the second screen that means I am going to edit this and if I pass null it means that I am creating a new item. The editing screen is a Stateful widget and I am not sure how to use this approach https://flutter.io/cookbook/navigation/passing-data/ for my case.

How can I access recordObject inside _RecordPageState?

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

7 Answers 7

To use recordObject in _RecordPageState, you have to just write widget.objectname like below

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

Full Example

You don’t need to pass parameters to State using it’s constructor. You can easily access these using widget.myField.

Pass your data when you Navigate screen :

stateful widget flutter передача параметров. Смотреть фото stateful widget flutter передача параметров. Смотреть картинку stateful widget flutter передача параметров. Картинка про stateful widget flutter передача параметров. Фото stateful widget flutter передача параметров

Often, you not only want to navigate to a new screen, but also pass data to the screen as well. For example, you might want to pass information about the item that’s been tapped.

In this example, create a list of todos. When a todo is tapped, navigate to a new screen (widget) that displays information about the Record. This recipe uses the following steps:

Define a RecordObject class

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *