November 30, 2014

Using Firebase from a Dart client and server

In my previous post I described how I created the ChessChallenge game using Polymer and Dart. Now I will make the game a bit more interesting by storing the ten best results in a list. To persist the list I chose Firebase, which is a simple but powerful way of storing and syncing data in realtime.
Another option would have been to use MongoDB on the server, which is included at DartVoid.

Below is a picture of the communication that takes place between the Client, Server and Firebase.


For the Client I used the Dart library firebase-dart, which wraps the standard JavaScript API. The Client listens for changes to the top list in Firebase and deserializes the data into a list of Users. You can also use onChildAdded if you want to receive events for the individual elements in the list.

  var fb = new Firebase('${firebaseUrl}/toplist');
  fb.onValue.listen((event) {
    List users = event.snapshot.val();
    if (users != null) topList =
        users.map((u) => new User.fromMap(u)).toList();
  });

For the server side the easiest way to read and write data is using the Firebase REST API. The whole top list will be written using a PUT request, see below. You can also use POST if you want to add single elements to a list.

  new HttpClient().putUrl(
      Uri.parse(
          '${firebaseUrl}/toplist.json')).then((HttpClientRequest request) {
    request.headers.contentType = ContentType.JSON;
    request.write(JSON.encode(topList));
    return request.close();
  }).then((HttpClientResponse response) {
    response.transform(UTF8.decoder).listen((contents) {
      print('Stored new top list in Firebase: ${contents}');
    });
  });

Dart does not give you automatic serialization support for classes, so you need to add it yourself.
Below is the code for the User class. There are several ways you can do this without having to write this code manually, for example using annotations and library support.

class User {
  String name;
  int avatar;
  int score = 0;
  int time;

  User(this.name, this.avatar);

  User.fromMap(Map map) {
    name = map['name'];
    avatar = map['avatar'];
    score = map['score'];
    time = map['time'];
  }

  Map toJson() {
    return {
      'name': name,
      'avatar': avatar,
      'score': score,
      'time': time
    };
  }
}

I was amazed how easy it was to use Firebase for adding the top 10 list feature. Firebase also has good support for authentication and security, but I will look into that another time.

The code is available on GitHub.

No comments:

Post a Comment