Flutter 从构建上下文中显示snackbar时查找停用的小部件
我有一个屏幕,可以绘制多个子部件,称为EventCard。每个卡都有一个可以单击的切换按钮,它将发送一个redux操作来触发HTTP调用,以便使用其中一个选项(切换按钮)更新数据库中的模型 http调用完成后,我们检查API的响应,如果一切正常,我们希望在屏幕上显示snackbar 当我们使用(Flutter 从构建上下文中显示snackbar时查找停用的小部件,flutter,flutter-redux,Flutter,Flutter Redux,我有一个屏幕,可以绘制多个子部件,称为EventCard。每个卡都有一个可以单击的切换按钮,它将发送一个redux操作来触发HTTP调用,以便使用其中一个选项(切换按钮)更新数据库中的模型 http调用完成后,我们检查API的响应,如果一切正常,我们希望在屏幕上显示snackbar 当我们使用(Scaffold.of(buildContext).showSnackBar()函数时会出现问题,因为buildContext已经卸载,所以我得到错误: 查找停用小部件的祖先是不安全的。 此时,小部件元素
Scaffold.of(buildContext).showSnackBar()
函数时会出现问题,因为buildContext已经卸载,所以我得到错误:
查找停用小部件的祖先是不安全的。
此时,小部件元素树的状态不再稳定。
要在dispose()方法中安全地引用小部件的祖先,请通过在小部件的didChangeDependencies()方法中调用inheritFromWidgetOfExactType()保存对祖先的引用。)
以下是my screen组件的构建功能:
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, EventScreenModel>(
model: EventScreenModel(),
builder: (BuildContext context, EventScreenModel model) {
final int childCount = model.events[model.currentRoleId] != null
? model.events[model.currentRoleId].length
: 0;
return Scaffold(
appBar: CustomAppBar(),
body: model.isLoading
? Center(
child: PulsingLogo(),
)
: Scrollbar(
child: CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.only(
top: 24.0, left: 24.0, bottom: 10.0),
child: Text(
'Moje udalosti',
style: Theme.of(context).textTheme.headline,
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
Event.Event event =
model.events[model.currentRoleId][index];
String role;
model.roles.forEach((i, acc) {
acc.forEach((listOfRoles) {
if (listOfRoles.academy_id == event.academy_id) {
role = listOfRoles.role;
}
});
});
return Padding(
padding:
const EdgeInsets.symmetric(horizontal: 16.0),
child: EventCard(
event: event,
currentRoleId: model.currentRoleId,
role: role,
),
);
}, childCount: childCount),
),
if (childCount == 0)
SliverToBoxAdapter(
child: Center(
child: Padding(
padding: const EdgeInsets.all(36.0),
child: Text('Nenašli sa žiadne udalosti.'),
),
),
),
SliverToBoxAdapter(
child: FractionallySizedBox(
widthFactor: 0.8,
child: RaisedButton(
onPressed: () {},
child: Text('Načítať dalšie'),
),
),
)
],
),
),
drawer: Menu(),
);
}
);
}
import 'package:academy_app/components/switch_button.dart';
import 'package:academy_app/main.dart';
import 'package:academy_app/screens/events_screen.dart';
import 'package:academy_app/state/event_state.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:academy_app/models/event.dart';
class EventCard extends StatelessWidget {
const EventCard(
{Key key,
@required this.event,
this.showAttendanceButton = true,
this.role,
this.currentRoleId})
: super(key: key);
final Event event;
final bool showAttendanceButton;
final String role;
final int currentRoleId;
bool get isGoing {
if (role != null && role != 'player')
return event.coaches != null
? event.coaches
.firstWhere((coach) => coach.id == currentRoleId)
.pivot
.participate
: false;
return event.players != null
? event.players
.firstWhere((player) => player.id == currentRoleId)
.pivot
.participate
: false;
}
_changeAttendance(context) {
store.dispatch(
SetEventAttendanceAction(
eventId: event.id,
isGoing: !isGoing,
buildContext: context,
roleId: currentRoleId),
);
}
String getDay(String date) => DateTime.parse(date).day.toString();
String getMonth(String date) =>
DateFormat('MMM').format(DateTime.parse(date)).toUpperCase();
String getTime(String date) =>
DateFormat('HH:mm').format(DateTime.parse(date));
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
if (event != null)
Card(
child: ListTile(
title: Text(
event.name,
style: Theme.of(context).textTheme.title,
),
subtitle: Text(
getTime(event.start_time) + '-' + getTime(event.end_time),
),
leading: Container(
margin: EdgeInsets.all(4.0),
padding: EdgeInsets.all(5.0),
decoration: BoxDecoration(
color: Colors.orange[400],
borderRadius: BorderRadius.circular(4.0),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
getDay(event.start_time),
style: TextStyle(color: Colors.white),
),
Text(
getMonth(event.end_time),
style: TextStyle(color: Colors.white),
),
],
),
),
trailing: AttendanceSwitchButton(
onPressed: () => _changeAttendance(context),
isGoing: isGoing,
small: true,
),
),
),
],
);
}
}
@覆盖
小部件构建(构建上下文){
返回存储连接器(
模型:EventScreenModel(),
生成器:(BuildContext上下文,EventScreenModel){
final int childCount=model.events[model.currentRoleId]!=null
?model.events[model.currentRoleId].length
: 0;
返回脚手架(
appBar:CustomAppBar(),
正文:model.isLoading
?中心(
子项:PulsingLogo(),
)
:滚动条(
子:自定义滚动视图(
条子:[
滑动双轴适配器(
孩子:填充(
填充:仅限常量边设置(
顶部:24.0,左侧:24.0,底部:10.0),
子:文本(
“Moje udalosti”,
风格:Theme.of(context).textTheme.headline,
),
),
),
银表(
代表:SliverChildBuilderDelegate(
(BuildContext上下文,int索引){
事件,事件=
model.events[model.currentRoleId][index];
字符串角色;
模型.角色.forEach((i,acc){
根据forEach((孔列表){
if(listOfRoles.academy\u id==event.academy\u id){
role=listOfRoles.role;
}
});
});
返回填充(
衬垫:
常数边集对称(水平:16.0),
孩子:事件卡(
事件:事件,,
currentRoleId:model.currentRoleId,
角色:角色,,
),
);
},childCount:childCount),
),
if(childCount==0)
滑动双轴适配器(
儿童:中心(
孩子:填充(
填充:常数边集全部(36.0),
儿童:文本(“Nenašli sažiadne udalosti.”),
),
),
),
滑动双轴适配器(
孩子:部分物理盒子(
宽度系数:0.8,
孩子:升起按钮(
按下:(){},
儿童:文本(“Načtaťdalšie”),
),
),
)
],
),
),
抽屉:菜单(),
);
}
);
}
下面是子事件卡组件:
@override
Widget build(BuildContext context) {
return StoreConnector<AppState, EventScreenModel>(
model: EventScreenModel(),
builder: (BuildContext context, EventScreenModel model) {
final int childCount = model.events[model.currentRoleId] != null
? model.events[model.currentRoleId].length
: 0;
return Scaffold(
appBar: CustomAppBar(),
body: model.isLoading
? Center(
child: PulsingLogo(),
)
: Scrollbar(
child: CustomScrollView(
slivers: <Widget>[
SliverToBoxAdapter(
child: Padding(
padding: const EdgeInsets.only(
top: 24.0, left: 24.0, bottom: 10.0),
child: Text(
'Moje udalosti',
style: Theme.of(context).textTheme.headline,
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
Event.Event event =
model.events[model.currentRoleId][index];
String role;
model.roles.forEach((i, acc) {
acc.forEach((listOfRoles) {
if (listOfRoles.academy_id == event.academy_id) {
role = listOfRoles.role;
}
});
});
return Padding(
padding:
const EdgeInsets.symmetric(horizontal: 16.0),
child: EventCard(
event: event,
currentRoleId: model.currentRoleId,
role: role,
),
);
}, childCount: childCount),
),
if (childCount == 0)
SliverToBoxAdapter(
child: Center(
child: Padding(
padding: const EdgeInsets.all(36.0),
child: Text('Nenašli sa žiadne udalosti.'),
),
),
),
SliverToBoxAdapter(
child: FractionallySizedBox(
widthFactor: 0.8,
child: RaisedButton(
onPressed: () {},
child: Text('Načítať dalšie'),
),
),
)
],
),
),
drawer: Menu(),
);
}
);
}
import 'package:academy_app/components/switch_button.dart';
import 'package:academy_app/main.dart';
import 'package:academy_app/screens/events_screen.dart';
import 'package:academy_app/state/event_state.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:academy_app/models/event.dart';
class EventCard extends StatelessWidget {
const EventCard(
{Key key,
@required this.event,
this.showAttendanceButton = true,
this.role,
this.currentRoleId})
: super(key: key);
final Event event;
final bool showAttendanceButton;
final String role;
final int currentRoleId;
bool get isGoing {
if (role != null && role != 'player')
return event.coaches != null
? event.coaches
.firstWhere((coach) => coach.id == currentRoleId)
.pivot
.participate
: false;
return event.players != null
? event.players
.firstWhere((player) => player.id == currentRoleId)
.pivot
.participate
: false;
}
_changeAttendance(context) {
store.dispatch(
SetEventAttendanceAction(
eventId: event.id,
isGoing: !isGoing,
buildContext: context,
roleId: currentRoleId),
);
}
String getDay(String date) => DateTime.parse(date).day.toString();
String getMonth(String date) =>
DateFormat('MMM').format(DateTime.parse(date)).toUpperCase();
String getTime(String date) =>
DateFormat('HH:mm').format(DateTime.parse(date));
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
if (event != null)
Card(
child: ListTile(
title: Text(
event.name,
style: Theme.of(context).textTheme.title,
),
subtitle: Text(
getTime(event.start_time) + '-' + getTime(event.end_time),
),
leading: Container(
margin: EdgeInsets.all(4.0),
padding: EdgeInsets.all(5.0),
decoration: BoxDecoration(
color: Colors.orange[400],
borderRadius: BorderRadius.circular(4.0),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
getDay(event.start_time),
style: TextStyle(color: Colors.white),
),
Text(
getMonth(event.end_time),
style: TextStyle(color: Colors.white),
),
],
),
),
trailing: AttendanceSwitchButton(
onPressed: () => _changeAttendance(context),
isGoing: isGoing,
small: true,
),
),
),
],
);
}
}
import'包:academy_应用程序/组件/开关_按钮.dart';
导入“包:academy_app/main.dart”;
导入“package:academy_app/screens/events_screen.dart”;
导入“package:academy_app/state/event_state.dart”;
进口“包装:颤振/材料.省道”;
导入“包:intl/intl.dart”;
导入“package:academy_app/models/event.dart”;
类EventCard扩展了无状态小部件{
常数事件卡(
{键,
@本次活动要求:,
this.showatendancebutton=true,
这个角色,,
这是(currentRoleId})
:super(key:key);
最终事件;
最后一个bool showAttendanceButton;
最终字符串角色;
最终int currentRoleId;
我要走了{
如果(角色!=null&&role!='player')
return event.coach!=null
?活动教练
.firstWhere((coach)=>coach.id==currentRoleId)
支点
.参与
:假;
return event.players!=null
?事件。玩家
.firstWhere((player)=>player.id==currentRoleId)
支点
.参与
:假;
}
_更改出席(上下文){
仓库调度(
SetEventAttentidanceAction(
eventId:event.id,
我要走了!我要走了,
buildContext:context,
roleId:currentRoleId),
);
}
String getDay(String date)=>DateTime.parse(date.day.toString();
字符串getMonth(字符串日期)=>
DateFormat('MMM').format(DateTime.parse(date)).toUpperCase();
字符串获取时间(字符串日期)=>
DateFormat('HH:mm').format(DateTime.parse(date));
@凌驾
小部件构建(构建上下文){
返回列(
儿童:[
如果(事件!=null)
卡片(
孩子:ListTile(
标题:正文(
event.name,
样式:Theme.of(context).textTheme.title,
),
字幕:文本(
getTime(event.st
Widget build(BuildContext context) {
Globals.currentContext = context;
... truncated
}
Scaffold.of(Globals.currentContext).showSnackBar