Flutter:Firebase实时混乱聊天

时间:2018-07-17 21:34:52

标签: firebase firebase-realtime-database dart flutter

我正在使用Flutter创建应用程序,我使用了实时Firebase插件。

实时插入Firebase: https://pub.dartlang.org/packages/firebase_database

我正在建立一个聊天室,用户可以在其中发送消息。

第一次是合适的,但是当我回到聊天室时,消息变得混乱了。

enter image description here

ChatScreenState

class ChatScreenState extends State<chatScreen> {
final TextEditingController _textController = new TextEditingController();
bool _isTyping = false;
// Firebase Database Chats
List<ChatsItems> items = List();
ChatsItems item;
DatabaseReference itemRef;

@override
void initState() {
  super.initState();

  // Chats
  item = ChatsItems("","","");
  final FirebaseDatabase database = FirebaseDatabase.instance;
  itemRef = database.reference().child(player_game_platform).child("CHAT");

  itemRef.onChildAdded.listen(_onEntryAdded);
  itemRef.onChildChanged.listen(_onEntryChanged);
}


// Chats
_onEntryAdded(Event event) {
  setState(() {
    items.add(ChatsItems.fromSnapshot(event.snapshot));
});
}

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


@override
Widget build(BuildContext context) {
return new Scaffold(
  appBar: new AppBar(
    title: new Text("Flutter Chat"),
    elevation: Theme.of(context).platform == TargetPlatform.iOS ? 0.0 : 4.0,
  ),
  body: new Container(
      child: new Column(
        children: <Widget>[
          new Flexible(
              child: new FirebaseAnimatedList(
                query: itemRef,
                sort: (a, b) => b.key.compareTo(a.key),
                padding: new EdgeInsets.all(8.0),
                reverse: true,
                itemBuilder: (_, DataSnapshot snapshot, Animation<double> animation, int index) {
                  return new ChatMessage(
                      snapshot: snapshot,
                      animation: animation,
                  );
                },
              )
          ),
          new Divider(height: 1.0),
          new Container(
            decoration: new BoxDecoration(
                color: Theme.of(context).cardColor),
            child: _buildTestComposer(),
          ),
        ],
      ),
      decoration: Theme.of(context).platform == TargetPlatform.iOS ? new BoxDecoration(border: new Border(top: new BorderSide(color: Colors.grey[200]))) : null),//new
);
} 


Widget _buildTestComposer() {
return new IconTheme(
    data: new IconThemeData(color: Theme.of(context).accentColor),
    child: new Container(
      margin: const EdgeInsets.symmetric(horizontal: 8.0),
      child: new Row(
          children: <Widget>[
            new Flexible(
              child: new TextField(
                controller: _textController,
                onChanged: (String text) {
                  setState(() {
                    _isTyping = true;
                  });
                },
                onSubmitted: _handleSubmitted,
                decoration: new InputDecoration.collapsed(hintText: "Introduzca su mensaje"),
              ),
            ),
            new Container(
              margin: new EdgeInsets.symmetric(horizontal: 4.0),
              child: Theme.of(context).platform == TargetPlatform.iOS ?
              new CupertinoButton(
                child: new Text("Enviar"),
                onPressed: _isTyping ? () =>_handleSubmitted(_textController.text) : null,
              ) :

              new IconButton(
                icon: new Icon(Icons.send),
                onPressed: _isTyping ?
                    () => _handleSubmitted(_textController.text) :
                null,
              ),
            ),

          ]
      ),
    )
);
}

Future<Null> _handleSubmitted(String player_message) async {
_textController.clear();
setState(() {
  _isTyping = false;
});
_sendMessage(
  player_message:player_message,
  player_avatar: player_avatar,
  player_user: player_user,
);
}

void _sendMessage({ String player_message, String player_avatar, String player_user, int player_id}) {
item.player_user = player_user;
item.player_avatar = player_avatar;
item.player_message = player_message;
itemRef.push().set(item.toJson());
}

}

ChatMessage

class ChatMessage extends StatelessWidget {
List<ChatsItems> items = List();


@override
Widget build(BuildContext context) {
return new SizeTransition(
    sizeFactor: new CurvedAnimation(
        parent: animation,
        curve: Curves.easeOut
    ),
    axisAlignment: 0.0,
    child: new Container(
      margin: const EdgeInsets.symmetric(vertical: 10.0),
      child: new ListTile(
        leading: new Container(
          width: 60.0,
          height: 60.0,
          decoration: new BoxDecoration(
            shape: BoxShape.circle,
            image: new DecorationImage(
                image: new AssetImage(items[contador].player_avatar),
                fit: BoxFit.fill
            ),
            color: Colors.lightBlue,
            border: Border.all(
              color: Colors.black,
              width: 2.0,
            ),
          ),
        ),
        title: new Text(items[contador].player_user, style: new TextStyle(color: Colors.black),),
        subtitle: new Text(items[contador].player_message),
      ),
    )
);
}
}

ChatsItems

class ChatsItems {
String key;
String player_user, player_message, player_avatar, message_id;

  ChatsItems(
      this.player_user,
      this.player_avatar,
      this.player_message,
  );

  ChatsItems.fromSnapshot(DataSnapshot snapshot)
      : key = snapshot.key,
        player_user = snapshot.value["player_user"],
        player_avatar = snapshot.value["player_avatar"],
        player_message = snapshot.value["player_message"];


  toJson() {
    return {
      "player_user": player_user,
      "player_avatar": player_avatar,
      "player_message": player_message,
    };
  }
}

我希望解决这个问题,感谢您的帮助。

**

更新于2018年7月20日

**

我已经删除了行的顺序,但是仍然出现相同的问题。这是我如何记录Firebase数据的清晰示例:

我正在用两部手机模拟通话,但是离开应用程序时却没有遵循顺序

1º注册后,它把我搞砸了。 https://www.gyazo.com/c80b86a77d8f8db35d1be16b0712a3e0

2º一张在Firebase中注册的数据外观的照片。 https://www.gyazo.com/2b272dfa41d4c4f30e3f86f3d9909dfb

3º第一个看起来正确的聊天室是当我重新打开聊天室时,由于firebase导致我的注册混乱,我搞砸了

https://www.gyazo.com/845fa21b93e4aa7fe094250e64c47084

2 个答案:

答案 0 :(得分:1)

我无法尝试您的代码,但我认为您遇到的问题在此行中

sort: (a, b) => b.key.compareTo(a.key),

尝试更改这种排序方式,或者如果它不是各个小部件的必需属性,则将其删除,然后再次尝试运行您的代码。整个代码中的重新排列只能通过这部分代码来实现。否则我看不到任何错误。可能导致这种情况。

答案 1 :(得分:0)

query: itemRef.orderByChild("message_id"),

我使用了 orderByChild (“ message_id ”),其中message_id包含日期时间,我下令了。

message_id = ServerValue.timestamp;

FirebaseAnimatedList添加此行:

    sort: (a, b) => b.value['message_id'].toString().compareTo(a.value['message_id'].toString()),