Я начинаю изучать Flutter, и мне любопытно, как передать данные между виджетами и сделать представление недействительным (перерисовать), когда я изменяю данные (состояние) в родительском виджете.
Я пытался сделать пользовательскийВиджет под названием Spinner: https://developer.android.com/guide/topics/ui/controls/spinner
Итак, я создал следующие классы:
class SpinnerWidget<T> extends StatefulWidget {
final SpinnerAdapter<T> adapter;
final String hint;
final bool allowClear;
final Function(T) onChanged;
SpinnerWidget({this.adapter, this.hint, this.allowClear, this.onChanged, Key key}) : super(key: key);
@override
_SpinnerWidgetState createState() =>
_SpinnerWidgetState(this.adapter, this.hint, this.allowClear, this.onChanged);
}
class _SpinnerWidgetState<T> extends State<SpinnerWidget> {
SpinnerAdapter<T> adapter;
String hint;
bool allowClear;
Function(T) onChanged;
T _selectedValue;
_SpinnerWidgetState(this.adapter, this.hint, this.allowClear, this.onChanged);
@override
Widget build(BuildContext context) {
return Container(
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(
side: BorderSide(
width: 1.0,
style: BorderStyle.solid,
color: Theme.of(context).textTheme.display1.color),
borderRadius: BorderRadius.all(Radius.circular(5.0))),
),
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 12),
child: DropdownButton<T>(
value: _selectedValue,
hint: Text(hint),
isExpanded: true,
underline: Container(
height: 0,
),
icon: allowClear ? (_selectedValue == null
? Icon(Icons.arrow_drop_down)
: IconButton(
icon: Icon(Icons.close),
padding: EdgeInsets.all(0.0),
onPressed: () {
setState(() {
_selectedValue = null;
});
if(onChanged != null)
onChanged(null);
},
)):Icon(Icons.arrow_drop_down),
items: adapter.getDropdownItems(),
onChanged: (T newValue) {
setState(() {
_selectedValue = newValue;
});
if(onChanged != null)
onChanged(newValue);
},
)),
);
}
}
abstract class SpinnerAdapter<T> {
final List<T> _items;
SpinnerAdapter(this._items);
Widget getChildWidget(T item);
List<DropdownMenuItem<T>> getDropdownItems() {
return _items.map((T item) => DropdownMenuItem(
value: item,
child: getChildWidget(item),
))
.toList();
}
}
Теперь в родительском виджете называется RegistrationPage
class RegistrationPage extends StatefulWidget {
RegistrationPage({Key key}) : super(key: key);
@override
_RegistrationPageState createState() => _RegistrationPageState();
}
class _RegistrationPageState extends State<RegistrationPage> {
MjesnaZajednicaAdapter adapter = MjesnaZajednicaAdapter(["One", "Two", "Three", "Four"]);
@override
Widget build(BuildContext context) {
return Scaffold(
// ...
SpinnerWidget<String>(
adapter: adapter,
hint: "Mjesna Zajednica",
allowClear: true,
), // SpinnerWidget
// ...
); // Scaffold
}
onUpdateSpinnerDataButtonPressed() {
setState(() {
adapter = MjesnaZajednicaAdapter(["Jedan", "Dva", "Tri", "Cetiri", "Pet"]);
});
}
}
Но когда я нажимаю эту кнопку, которая появляется у меня на экране, и выполняется метод onUpdateSpinnerDataButtonPressed
, у меня остаются те же значения в Spinner.
Любая помощь в том, как мне обновить состояние потомков. Я прочитал кое-что о GlobalKey и попробовал это, но я не уверен, как использовать это, когда иерархия виджетов состоит из нескольких уровней.
Например, что если у меня что-то вроде этого:
RegistrationPage -> RegistrationForm -> SpinnerWidget
Теперь в RegistrationPage я вызвал службу для извлечения данных из Интернета для виджета счетчика, тогда мне нужночтобы передать это в регистрационную форму, которая, наконец, передаст ее SpinnerWidget ... Я знаю, что могу вызвать службу из виджета RegistrationForm, но только для примера, я хочу вызвать ее из RegistrationPage.