Flutter 从构建上下文中显示snackbar时查找停用的小部件

Flutter 从构建上下文中显示snackbar时查找停用的小部件,flutter,flutter-redux,Flutter,Flutter Redux,我有一个屏幕,可以绘制多个子部件,称为EventCard。每个卡都有一个可以单击的切换按钮,它将发送一个redux操作来触发HTTP调用,以便使用其中一个选项(切换按钮)更新数据库中的模型 http调用完成后,我们检查API的响应,如果一切正常,我们希望在屏幕上显示snackbar 当我们使用(Scaffold.of(buildContext).showSnackBar()函数时会出现问题,因为buildContext已经卸载,所以我得到错误: 查找停用小部件的祖先是不安全的。 此时,小部件元素

我有一个屏幕,可以绘制多个子部件,称为EventCard。每个卡都有一个可以单击的切换按钮,它将发送一个redux操作来触发HTTP调用,以便使用其中一个选项(切换按钮)更新数据库中的模型

http调用完成后,我们检查API的响应,如果一切正常,我们希望在屏幕上显示snackbar

当我们使用(
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