Flutter:Firebase Realtime从对象列表中删除对象

时间:2018-08-19 15:34:51

标签: firebase firebase-realtime-database dart flutter

我正在咨询数据库中注册的所有俱乐部。对于每个俱乐部,我都将其添加到对象列表中。

当个人删除俱乐部时,将从数据库中删除俱乐部,但是在项目列表中没有删除,我尝试执行以下操作:

我的NotClub-Player.dart类

// FIREBASE CLUBS
List<Club> items = List();
Club item;
DatabaseReference itemRef;

@override
void initState() {
   super.initState();
   item = Club("","","",0,"","","","",0,0,false,"","","","","",false,"","","","","","","","","","","");
   final FirebaseDatabase database = FirebaseDatabase.instance;
   itemRef = database.reference().child(player.player_game_platform).child("CLUB");
   itemRef.onChildAdded.listen(_onEntryAdded);
   itemRef.onChildRemoved.listen(_onEntryRemoved);
   itemRef.onChildChanged.listen(_onEntryChanged);
}

// CLUBS LISTENERS
_onEntryAdded(Event event) {
 setState(() {
   items.add(Club.fromSnapshot(event.snapshot));
 });
}

_onEntryRemoved(Event event) {
 setState(() {
   items.remove(Club.fromSnapshot(event.snapshot));
 });
}

_onEntryChanged(Event event) {
 var old = items.singleWhere((entry) {
   return entry.key == event.snapshot.key;
 });
 setState(() {
   items[items.indexOf(old)] = Club.fromSnapshot(event.snapshot);
 });
}

我的问题: _onEntryRemoved 中有一个事件。在这种情况下,它将返回已删除的项目。但是它不会从列表中删除相应的项目。

在数据库中,已成功将其删除。但是包含对象的列表尚未将其删除。

这是我的查询

rnew Flexible(
            child: new FirebaseAnimatedList(
              query: FirebaseDatabase.instance.reference().child(player.player_game_platform).child("CLUB").orderByChild("club_name"),
              itemBuilder: (BuildContext context, DataSnapshot snapshot,
                  Animation<double> animation, int index) {
                return new Column(
                  children: <Widget>[
                    new Container(
                      decoration: new BoxDecoration(
                        color: Colors.grey[300],
                      ),
                      child: new ListTile(
                        leading: new CachedNetworkImage(imageUrl: items[index].club_logo, width: 60.0),
                        title: new Text(items[index].club_name, style: new TextStyle(color: Colors.black)),
                        subtitle: new Text("CAPTAIN: "+items[index].club_captain, style: new TextStyle(color: Colors.black)),
                        trailing: new RaisedButton(
                            color: Colors.lightBlue[500],
                            child: new Text("JOIN", style: new TextStyle(color: Colors.white)),
                            onPressed: (){

                            }
                        ),
                      ),
                    ),
                    new Divider(
                      color: Colors.grey[700],
                      height: 0.0,
                    ),
                  ],
                );
              },
            ),
          ),

这是我在_onEntryRemoved中得到的信息 -它返回正确的删除,但是删除列表不适用于我。

E/flutter (15214): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (15214): setState() called after dispose(): _join_clubState#a99f1(lifecycle state: defunct, not mounted)
E/flutter (15214): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter (15214): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
E/flutter (15214): #0      State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1098:9)
E/flutter (15214): #1      State.setState (package:flutter/src/widgets/framework.dart:1124:6)
E/flutter (15214): #2      _join_clubState._onEntryRemoved (package:proclubscommunity/Club-Player.dart:807:5)
E/flutter (15214): #3      _RootZone.runUnaryGuarded (dart:async/zone.dart:1316:10)
E/flutter (15214): #4      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:330:11)
E/flutter (15214): #5      _DelayedData.perform (dart:async/stream_impl.dart:578:14)
E/flutter (15214): #6      _StreamImplEvents.handleNext (dart:async/stream_impl.dart:694:11)
E/flutter (15214): #7      _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:654:7)
E/flutter (15214): #8      _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (15214): #9      _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
I/flutter (15214): {club_logo: url_image, club_note: , club_since: , club_three_position: , club_market: false, club_market_color: , club_six_position: , club_premium: false, club_twitter: https://www.twitter.com/, club_first_position: , club_category: 0, club_seven_position: , club_description: , club_copa: 0, club_country: ESPAÑA, club_liga: 0, club_four_position: , club_logo_file_name: club_logo.png, club_plataform: PS4, club_nine_position: , club_captain: RaiiLKilleR, club_name: Barcelona, club_five_position: , club_eight_position: , club_id: 1, club_second_position: , club_logo_folder_name: PS4_Barcelona, club_twitch: https://www.twitch.tv/, club_youtube: https://www.youtube.com/}

向小部件添加密钥:

            return new Column(
              key: new ObjectKey(items[index].club_name),
              children: <Widget>[
                new Container(
                  decoration: new BoxDecoration(
                    color: Colors.grey[300],
                  ),
                  child: new ListTile(
                    leading: new CachedNetworkImage(imageUrl: items[index].club_logo, width: 60.0),
                    title: new Text(items[index].club_name, style: new TextStyle(color: Colors.black)),
                    subtitle: new Text("Captain: "+items[index].club_captain, style: new TextStyle(color: Colors.black)),
                    trailing: new RaisedButton(
                        color: Colors.lightBlue[500],
                        child: new Text("JOIN", style: new TextStyle(color: Colors.white)),
                        onPressed: (){

                        }
                    ),
                  ),
                ),
                new Divider(
                  color: Colors.grey[700],
                  height: 0.0,
                ),
              ],
            );

_onEntryRemoved()

  _onEntryRemoved(Event event) {
    setState(() {
      print(event.snapshot.value['club_name']);
      items.remove(event.snapshot.value['club_name']);
    });
  }

1 个答案:

答案 0 :(得分:1)

您的问题出在Club上。

在创建List<Club> items并随后执行items.remove(clubInstance)时,内部的remove方法将使用标准对象equals方法实现,而该实现不知道您的密钥。

如果您尝试使用items.indexOf(clubInstance),也会发生同样的情况。它永远不会“找到”该项目,总是返回-1

您可以更改实现,遍历各个项目以准确找出需要删除的项目,然后将其删除,或者可以在Club类中实现==hashCode

如果您打算使用club_name作为键,则添加这两行可能会解决。

class Club {
  Club({this.club_name});
  final String club_name;

  // this is what you would have to add to your class:
  bool operator ==(o) => o is Club && o.club_name == club_name;
  int get hashCode => club_name.hashCode;
}

注意:这与颤振或火力无关,这只是飞镖!