mar*_*rop 4 java android firebase firebase-realtime-database
我的数据库中有一个用户节点,用于存储有关用户的任何信息。然后在我的应用程序中我必须对按钮进行图像处理:
mlike = root.findViewById(R.id.btn_like);
mdislike = root.findViewById(R.id.btn_dislike);
mlike.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
likeStations();
}
});
mdislike.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dislikeStations();
}
});
private void dislikeStations(){
db = FirebaseDatabase.getInstance();
ref = db.getReference().child("Users").child(user);
DatabaseReference likesRef = FirebaseDatabase.getInstance().getReference().child("STATIONS").child(station);
likesRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Boolean dislike_snapshot = dataSnapshot.child("downvote").getValue(Boolean.class);
likeref.child("downvote").setValue(+1)
}
}
Run Code Online (Sandbox Code Playgroud)
对于 likeStations() 方法来说,情况几乎是一样的。我想知道的是如何确保他们只能单击按钮一次,或者如果他们在单击不喜欢后单击“喜欢”,则会在“喜欢”上添加 1 之前从“不喜欢”中删除 1。
我知道它将使用用户节点,因此我将其添加到问题中。
它总是从拥有正确的数据结构开始。如果您希望用户只被允许执行一次操作,您需要:
由于您想分别跟踪赞成票和反对票,那就是:
upvotes: {
"uid1": true,
"uid2": true
},
downvotes: {
"uid3": true
}
Run Code Online (Sandbox Code Playgroud)
现在,您的其余要求是该结构上的一堆安全规则。
例如,允许用户为自己投票,如下所示:
{
"rules": {
...
"upvotes": {
"$uid": {
".write": "auth.uid === $uid"
}
},
"downvotes": {
"$uid": {
".write": "auth.uid === $uid"
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
接下来,用户只能投赞成票或反对票,而不能同时投赞成票或反对票,如下所示:
"upvotes": {
"$uid": {
".write": "auth.uid === $uid
&& !newData.parent().parent().child('downvotes').child(auth.uid).exists()"
}
},
Run Code Online (Sandbox Code Playgroud)
当然,还有同样的规则downvotes。
根据上述规则,用户可以使用此 JSON 补丁(您可以在 Android 中将其构建为 a)投赞成票:Map
{
"upvotes/uid1": true
}
Run Code Online (Sandbox Code Playgroud)
否决票是:
{
"downvotes/uid1": true
}
Run Code Online (Sandbox Code Playgroud)
但如果他们已经投了赞成票,那么就会被拒绝,因此您可以通过执行此(单个)写入操作将他们的赞成票切换为反对票:
{
"upvotes/uid1": null,
"downvotes/uid1": true
}
Run Code Online (Sandbox Code Playgroud)
这里null删除他们的赞成票,并true写入反对票,两者都是作为单个操作发生的。
最后,这让我们谈到了您所询问的计数,这是与唯一性不同的主题。现在存储计数是可选的,因为该信息已经存在于 UID 的数量中。但这是一个很好的优化,因为如果没有存储的计数器,用户将必须下载所有 UID 值来对其进行计数。
那么数据结构就变成了:
upvotes: {
"uid1": true,
"uid2": true
},
upvoteCount: 2,
downvotes: {
"uid3": true
},
downvoteCount: 1
Run Code Online (Sandbox Code Playgroud)
现在您已经有了数据结构并且我们已经看到了转换,接下来就需要确保计数的变化与投票结果相匹配。
第一个例子是我们上面看到的赞成票片段:您可以在投赞成票时增加赞成票数。规则中
"upvoteCount": {
".write": "(
newData.val() = data.val() + 1
newData.parent().parent().child('upvotes').child(auth.uid).exists()
&& !data.parent().parent().child('upvotes').child(auth.uid).exists()
)"
}
Run Code Online (Sandbox Code Playgroud)
如果您阅读上面的定义,我希望这个表达式是有意义的:
upvotes列表中时,如果他们删除了投票,您同样需要处理减少赞成票数的问题,然后还要处理反对票数的问题。这些规则都很相似,但又是分开的。
一旦完成,最后一步是增强规则upvotes并downvotes要求用户在投票时更新计数。当用户投票时,他们还必须更新计数。这与我们刚刚看到的规则相反:
"upvotes": {
"$uid": {
".write": "auth.uid === $uid
&& newData.exists()
&& !data.exists()
&& newData.parent().parent().child('upvoteCount').val() ==
data.parent().parent().child('upvoteCount').val() + 1
}
},
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
353 次 |
| 最近记录: |