我被困住了,我认为我完全迷失了Flutter的逻辑。我要执行以下操作:
class HomeScreen extends StatefulWidget {
static String id = 'home_screen';
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
icon: Icon(Icons.refresh),
onPressed: () {
** I WANT TO CALL REFRESH ON THE EVENT LIST**
},
),
],
),
body: Column(
children: <Widget>[
EventList(),
...
class EventList extends StatefulWidget {
@override
_EventListState createState() => _EventListState();
}
class _EventListState extends State<EventList> {
List<Event> eventList = [];
@override
void initState() {
super.initState();
getEventList();
}
Future<Null> getEventList() async {
// Fill eventList from a web service ...
setState(() {
});
}
@override
Widget build(BuildContext context) {
return Expanded(
child: Container(
child: (eventList == null || eventList.length == 0)
? Center(
child: CircularProgressIndicator()
: ListView.builder(
itemCount: (eventList == null) ? 0 : eventList.length,
itemBuilder: (BuildContext context, int index) {
...
此逻辑用于在Web服务上使用GET进行首次数据提取。
如何调用refresh()在主屏幕上获取新数据并要求EventList刷新(再次调用getEventList())并重建?
谢谢
答案 0 :(得分:1)
有很多方法可以解决您的问题。
第一个是在获取数据后在MainState类中调用setState。这将导致所有子窗口小部件重新生成。但要这样做,您还需要将数据保存在MainState类中,并将其作为参数传递给EventList小部件。 (请注意,您的EventList小部件不再需要是有状态的!因为它不再应该调用setState方法)。
如果您确实希望将函数包含在EventListState类中,则第二个选择是创建一个在MainState类中实例化的控制器。但这对于像这样简单的任务来说是很多工作。
第三个是创建一个服务,该服务将是一个单独的类,公开一个Stream,您可以在需要时在其上推送数据。我知道这听起来可能很复杂,所以对于这个例子,这是一个理论示例:
class MyEventService {
final StreamController<List<Event>> stateStreamController = StreamController<List<Event>>.broadcast();
Stream<ActionState> get stateStream => stateStreamController.stream;
Future<void> refresh() { fetchFromServer... then stateStreamController.push(data);
}
class MainState {
build(..) => Scaffold(... Button(onPushed: myEventServiceInstance.refresh)
}
class EventList {
build(..) => StreamBuilder(stream: myEventServiceInstance.stream...)
}
希望这对您有所帮助,不要犹豫,问您是否需要更复杂的样本!
答案 1 :(得分:1)
您可以在下面复制粘贴运行完整代码
工作演示模拟3秒的网络延迟并显示随机数
步骤1:在setState
的{{1}}中调用IconButton
onPressed
步骤2:在IconButton(
icon: Icon(Icons.refresh),
onPressed: () {
setState(() {});
},
),
的{{1}}中使用didUpdateWidget
呼叫_EventListState
addPostFrameCallback
工作演示
单击刷新按钮时的执行顺序
getEventList()
完整代码
@override
void didUpdateWidget(EventList oldWidget) {
super.didUpdateWidget(oldWidget);
WidgetsBinding.instance.addPostFrameCallback((_) {
getEventList();
});
}
答案 2 :(得分:0)
在扑朔迷离中,您不能从父级调用子函数,我建议将它们组合在一个有状态的小部件中,或者将支架放入eventList小部件中,以便将应用程序栏和ListView放在同一statfull小部件中
class HomeScreen extends StatefulWidget {
static String id = 'home_screen';
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<Event> eventList = [];
@override
void initState() {
super.initState();
getEventList();
}
Future<Null> getEventList() async {
// Fill eventList from a web service ...
setState(() {
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: <Widget>[
IconButton(
icon: Icon(Icons.refresh),
onPressed: () => getEventList(),
),
],
),
body: Column(
children: <Widget>[
buildEventList(),
]
),);
}
Widget buildEventList()(BuildContext context) {
return Expanded(
child: Container(
child: (eventList == null || eventList.length == 0)
? Center(
child: CircularProgressIndicator()
: ListView.builder(
itemCount: (eventList == null) ? 0 : eventList.length,
itemBuilder: (BuildContext context, int index) {
..
}),
}
}