【问题标题】:How to implement upvote system without user authentication with Firebase?如何在不使用 Firebase 进行用户身份验证的情况下实现投票系统?
【发布时间】:2018-07-16 00:16:11
【问题描述】:

我正在构建一个应用程序,其中将使用 firebase 实现支持系统,但该应用程序没有用户 logi0/signup,我也不希望添加一个。我已阅读documentation on transaction() 以了解如何在我的应用程序中实现投票系统,但我不知道如何在没有用户登录的情况下使用它?我有一个类似于 Firebase 文档中给出的 Post 类

public class _Post {
public String uid;
public String timeStamp;
public String author;
public String body;
public int starCount = 0;
public Map<String, Boolean> stars = new HashMap<>();

public _Post() {
    // Default constructor required for calls to DataSnapshot.getValue(Post.class)
}

public _Post(String uid, String author, String body, String timeStamp) {
    this.uid = uid;
    this.author = author;
    this.body = body;
    this.timeStamp = timeStamp;
}

@Exclude
public Map<String, Object> toMap() {
    HashMap<String, Object> result = new HashMap<>();
    result.put("uid", uid);
    result.put("author", author);
    result.put("body", body);
    result.put("starCount", starCount);
    result.put("stars", stars);
    result.put("time", timeStamp);
    return result;
}

public String getUid() {
    return uid;
}

public String getTimeStamp() {
    return timeStamp;
}

public String getAuthor() {
    return author;
}

public String getBody() {
    return body;
}

public int getStarCount() {
    return starCount;
}

public Map<String, Boolean> getStars() {
    return stars;
}

}

这是我的投票方法,也是我从 firebase 文档/指南中获取的

private void onStarClicked(String postId, final String uid) {
    DatabaseReference postRef = mDatabaseRef.child("north_america").child("posts").child(postId);
    postRef.runTransaction(new Transaction.Handler() {
        @Override
        public Transaction.Result doTransaction(MutableData mutableData) {
            _Post p = mutableData.getValue(_Post.class);
            if (p == null) {
                return Transaction.success(mutableData);
            }

            if (p.stars.containsKey(uid)) {
                // Unstar the post and remove self from stars
                p.starCount = p.starCount - 1;
                p.stars.remove(uid);
            } else {
                // Star the post and add self to stars
                p.starCount = p.starCount + 1;
                p.stars.put(uid, true);
            }

            // Set value and report transaction success
            mutableData.setValue(p);
            return Transaction.success(mutableData);
        }

        @Override
        public void onComplete(DatabaseError databaseError, boolean b,
                               DataSnapshot dataSnapshot) {
            // Transaction completed
            Log.d(TAG, "postTransaction:onComplete:" + databaseError);
        }
    });
}

我遇到的另一个问题是我的 firebase Posts 节点会是什么样子? 也许像这样? (我的应用谈论即将上映的电影)

-- north_america
--- posts
---- movie_id

movie_id 会是这样的吗?

在本例中,1123 是电影的 id

"1123": {
    "uid": "user_2",
    "title": "I am legend"
    "likes": 0
}

Posts 节点中的 Post 对象将包含什么?

【问题讨论】:

  • 如果你的用户没有登录,你传入PostString uid是什么意思?
  • @FrankvanPuffelen 如果没有用户,这意味着设备可以增加多次,不是吗?我只希望设备增加一次
  • 听起来您希望在不要求用户提供凭据的情况下安全地识别设备/会话。为此,Firebase 提供匿名身份验证。见firebase.google.com/docs/auth/android/anonymous-auth。我也用更多关于此的信息更新了我的答案。

标签: android firebase firebase-realtime-database


【解决方案1】:

如果您希望在不要求用户提供凭据的情况下安全地识别设备/会话,您可以使用Firebase's anonymous authentication。这允许您通过简单地调用为当前设备上的用户创建一个“会话”:

FirebaseAuth.getInstance().signInAnonymously()

这会在客户端和(更重要的是)服务器上识别用户,这样您就可以确保每个用户只能投票一次。

如果您不关心限制每个用户的投票数,而只是想以事务方式增加电影的likes,请在每次点击时执行以下操作:

private void onStarClicked(String postId, final String uid) {
    DatabaseReference postRef = mDatabaseRef.child("north_america/posts").child(postId).child("likes");
    postRef.runTransaction(new Transaction.Handler() {
        @Override
        public Transaction.Result doTransaction(MutableData mutableData) {
            Long value = mutableData.getValue(Long.class);
            if (value == null) value = new Long(0);
            mutableData.setValue(value + 1);
            return Transaction.success(mutableData);

        }

        @Override
        public void onComplete(DatabaseError databaseError, boolean b,
                               DataSnapshot dataSnapshot) {
            // Transaction completed
            Log.d(TAG, "postTransaction:onComplete:" + databaseError);
        }
    });
}

代码只是在likes 属性上执行一个事务,增加它的值。

【讨论】:

  • 非常感谢!!您知道 Post 对象的外观吗?我在问题末尾提供的那个有用吗?
  • 如果用户已登录,我该如何完成此操作?
  • 您问题中的代码正是这样做的:它采用 UID 并记录对该用户的投票。
猜你喜欢
  • 1970-01-01
  • 2020-05-27
  • 2021-11-16
  • 2011-06-29
  • 2016-12-15
  • 1970-01-01
  • 1970-01-01
  • 2016-08-28
  • 1970-01-01
相关资源
最近更新 更多