Flutter - 使用相同的提供者更新下拉列表并将数据发送到另一个小部件
Flutter - using same provider for updating dropdown and sending to data to another widget
我想将所选值从 DropDown 传递到它的 parent,然后通过构造函数传递到 child,然后通过 setState 函数更新列表。
因此,我希望可以在限制 (UserOffers) 的 child 中访问从下拉列表中选择的值。
将数据从 parent 发送到 child 它确实有效,但仅当我将 parent class 中定义的数据传递给 child 时由构造函数 =我不确定这是否是一个好方法。
现在我正在使用提供程序来更新下拉列表中的数据,但我不知道如何传递它。
国家提供者class:
class CountryProvider with ChangeNotifier {
List<String> _items = [
"Argentina",
"Brazil",
...
"Spain",
"Switzerland",
];
String _selectedItem;
List<String> get items => _items;
String get selected => _selectedItem;
void setSelectedItem(String s) {
_selectedItem = s;
notifyListeners();
}
}
CountryDropDown class:
class CountryDropDown extends StatefulWidget {
@override
_CountryDropDownState createState() => _CountryDropDownState();
}
class _CountryDropDownState extends State<CountryDropDown> {
@override
void initState() {
super.initState();
}
...
ChangeNotifierProvider<CountryProvider>(
create: (context) => CountryProvider(),
child: Container(
width: 215,
child: Consumer<CountryProvider>(
builder: (_, provider, __) {
return DropdownButton<String>(
hint: Text("Not selected"),
icon: Icon(Icons.flight),
value: dropdownValue,
onChanged: (String newValue) {
provider.setSelectedItem(newValue);
dropdownValue = provider.selected;
print(newValue);
},
items: provider.items
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
...
和parent:
限制条件class:
class Restrictions extends StatefulWidget {
@override
_RestrictionsState createState() => _RestrictionsState();
}
class _RestrictionsState extends State<Restrictions> {
@override
void initState() {
super.initState();
}
...
Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 20),
child: FieldDropDown(),
),
Container(
padding: EdgeInsets.only(top: 10),
margin: EdgeInsets.only(left: 20),
child: CountryDropDown(),
),
],
),
Container(
child: DateSelector(),
),
],
),
Container(
child: UserOffers(
country: selectedCountry,
field: selectedField,
),
...
@Boras! ...
.
你为我做了很多工作
我认为您需要将状态提升到小部件树的更高位置,以便 UserOffers
可以在用户从下拉菜单中选择国家/地区时更改。
完成下面的示例应用程序。
请注意,我将模型 class 名称更改为 SingleSelectCountry
。该模型 class 的实例不是提供者。该模型的一个实例 class 是提供者提供的。这里有一个重要的区别。
另请注意,所有小部件都扩展了 StatelessWidget
。通常与包提供者你可以避免使用 StatefulWidget
.
import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
// Model ---------------------------------------------------
class SingleSelectCountry with ChangeNotifier {
final List<String> _items = <String>[
"Argentina",
"Belgium",
"Brazil",
"Denmark",
"England",
"France",
"Finland",
"Germany",
"Holland",
"Ireland",
"Norway",
"Poland",
"Scotland",
"Spain",
"Sweden",
"Switzerland",
"Wales",
];
String _selectedItem;
UnmodifiableListView<String> get items {
return UnmodifiableListView(this._items);
}
String get selected {
return this._selectedItem;
}
set selected(final String item) {
this._selectedItem = item;
this.notifyListeners();
}
}
// User Interface ------------------------------------------
void main() {
return runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(final BuildContext context) {
// The provider has to be in the widget tree higher than
// both `CountryDropDown` and `UserOffers`.
return MultiProvider(
providers: [
ChangeNotifierProvider<SingleSelectCountry>(
create: (final BuildContext context) {
return SingleSelectCountry();
},
),
],
child: Scaffold(
appBar: AppBar(
title: Text('My Home Page'),
),
body: Restrictions(),
),
);
}
}
class Restrictions extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return Column(
children: <Widget>[
CountryDropDown(),
UserOffers(),
],
);
}
}
class CountryDropDown extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return Consumer<SingleSelectCountry>(
builder: (
final BuildContext context,
final SingleSelectCountry singleSelectCountry,
final Widget child,
) {
return DropdownButton<String>(
hint: const Text("Not selected"),
icon: const Icon(Icons.flight),
value: singleSelectCountry.selected,
onChanged: (final String newValue) {
singleSelectCountry.selected = newValue;
},
items: singleSelectCountry.items.map<DropdownMenuItem<String>>(
(final String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
},
).toList(),
);
},
);
}
}
class UserOffers extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return Consumer<SingleSelectCountry>(
builder: (
final BuildContext context,
final SingleSelectCountry singleSelectCountry,
final Widget child,
) {
return Text(singleSelectCountry.selected ?? '');
},
);
}
}
我想将所选值从 DropDown 传递到它的 parent,然后通过构造函数传递到 child,然后通过 setState 函数更新列表。
因此,我希望可以在限制 (UserOffers) 的 child 中访问从下拉列表中选择的值。
将数据从 parent 发送到 child 它确实有效,但仅当我将 parent class 中定义的数据传递给 child 时由构造函数 =我不确定这是否是一个好方法。
现在我正在使用提供程序来更新下拉列表中的数据,但我不知道如何传递它。
国家提供者class:
class CountryProvider with ChangeNotifier {
List<String> _items = [
"Argentina",
"Brazil",
...
"Spain",
"Switzerland",
];
String _selectedItem;
List<String> get items => _items;
String get selected => _selectedItem;
void setSelectedItem(String s) {
_selectedItem = s;
notifyListeners();
}
}
CountryDropDown class:
class CountryDropDown extends StatefulWidget {
@override
_CountryDropDownState createState() => _CountryDropDownState();
}
class _CountryDropDownState extends State<CountryDropDown> {
@override
void initState() {
super.initState();
}
...
ChangeNotifierProvider<CountryProvider>(
create: (context) => CountryProvider(),
child: Container(
width: 215,
child: Consumer<CountryProvider>(
builder: (_, provider, __) {
return DropdownButton<String>(
hint: Text("Not selected"),
icon: Icon(Icons.flight),
value: dropdownValue,
onChanged: (String newValue) {
provider.setSelectedItem(newValue);
dropdownValue = provider.selected;
print(newValue);
},
items: provider.items
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
...
和parent:
限制条件class:
class Restrictions extends StatefulWidget {
@override
_RestrictionsState createState() => _RestrictionsState();
}
class _RestrictionsState extends State<Restrictions> {
@override
void initState() {
super.initState();
}
...
Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 20),
child: FieldDropDown(),
),
Container(
padding: EdgeInsets.only(top: 10),
margin: EdgeInsets.only(left: 20),
child: CountryDropDown(),
),
],
),
Container(
child: DateSelector(),
),
],
),
Container(
child: UserOffers(
country: selectedCountry,
field: selectedField,
),
...
@Boras! ...
.
我认为您需要将状态提升到小部件树的更高位置,以便 UserOffers
可以在用户从下拉菜单中选择国家/地区时更改。
完成下面的示例应用程序。
请注意,我将模型 class 名称更改为 SingleSelectCountry
。该模型 class 的实例不是提供者。该模型的一个实例 class 是提供者提供的。这里有一个重要的区别。
另请注意,所有小部件都扩展了 StatelessWidget
。通常与包提供者你可以避免使用 StatefulWidget
.
import 'dart:collection';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
// Model ---------------------------------------------------
class SingleSelectCountry with ChangeNotifier {
final List<String> _items = <String>[
"Argentina",
"Belgium",
"Brazil",
"Denmark",
"England",
"France",
"Finland",
"Germany",
"Holland",
"Ireland",
"Norway",
"Poland",
"Scotland",
"Spain",
"Sweden",
"Switzerland",
"Wales",
];
String _selectedItem;
UnmodifiableListView<String> get items {
return UnmodifiableListView(this._items);
}
String get selected {
return this._selectedItem;
}
set selected(final String item) {
this._selectedItem = item;
this.notifyListeners();
}
}
// User Interface ------------------------------------------
void main() {
return runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(final BuildContext context) {
// The provider has to be in the widget tree higher than
// both `CountryDropDown` and `UserOffers`.
return MultiProvider(
providers: [
ChangeNotifierProvider<SingleSelectCountry>(
create: (final BuildContext context) {
return SingleSelectCountry();
},
),
],
child: Scaffold(
appBar: AppBar(
title: Text('My Home Page'),
),
body: Restrictions(),
),
);
}
}
class Restrictions extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return Column(
children: <Widget>[
CountryDropDown(),
UserOffers(),
],
);
}
}
class CountryDropDown extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return Consumer<SingleSelectCountry>(
builder: (
final BuildContext context,
final SingleSelectCountry singleSelectCountry,
final Widget child,
) {
return DropdownButton<String>(
hint: const Text("Not selected"),
icon: const Icon(Icons.flight),
value: singleSelectCountry.selected,
onChanged: (final String newValue) {
singleSelectCountry.selected = newValue;
},
items: singleSelectCountry.items.map<DropdownMenuItem<String>>(
(final String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
},
).toList(),
);
},
);
}
}
class UserOffers extends StatelessWidget {
@override
Widget build(final BuildContext context) {
return Consumer<SingleSelectCountry>(
builder: (
final BuildContext context,
final SingleSelectCountry singleSelectCountry,
final Widget child,
) {
return Text(singleSelectCountry.selected ?? '');
},
);
}
}