我使用Firebase实时数据库和Firebase的云功能(使用事务)创建了类似于订阅/类似计数器的东西:
// This is a cloud function that increases subs by 1
export const onSubscriberCreate = functions.database
.ref('/channels/{$ch_id}/subscribers/{$uid}')
.onCreate((snapshot, context) => {
const countRef = snapshot.ref.parent.parent.child('subs_count')
return countRef.transaction(count => {
return count + 1
})
})
然后,我使用Android的FirebaseUI(FirebaseRecyclerAdapter)填充通道的RecyclerView。当用户按下频道的“订阅”按钮时,其ID将发送到/ channels / {$ ch_id} / subscribers /,这将触发云功能。
但是,云功能确实很慢(大约5秒),所以我想在执行云功能之前就“伪造”显示给用户的计数器更新(我通过更改TextView进行了尝试):
channelRef.child("subscribers")
.child(user.getUid()).setValue(true)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
subsInfo.setText(channel.getSubs_count() + 1) + " SUBSCRIBERS");
}
});
问题在于,通道对象被更新了两次(订户列表中的用户ID和计数器增加了),因此,即使在服务器更新通道对象之前,也要再次下载该通道的信息并绑定到ViewHolder。计数器,所以这不是一个好的解决方案。
我考虑过将交易代码移至客户端,这真的有必要吗?有更好的解决方案吗?
答案 0 :(得分:1)
我觉得您应该做的最好的事情是将订户列表从通道节点内部移到某个位置。这也将使您的频道对象的重量减轻,并且您可以轻松地在频道节点内部存储/更新订户数量。现在,对于每个用户,您每次要下载频道信息时都将下载整个用户列表。而且您不需要云功能即可更新订户数量。您可以使用事务完全在客户端上执行此操作。
\begin{center}
\begin{tabular}{ | m{7em} | m{5em}| m{9em} | }
\hline
Set & operation & Identity \\
\hline
\(\mathbb{Z}\) & \(+\) & \(0\) \\
\hline
\(\mathbb{Q}\) & \(+\) & \(0\) \\
\hline
\(\mathbb{R}\) & \(+\) & \(0\) \\
\hline
\(\mathbb{Z}\) & \(\times \) & \(0\) \\
\hline
\(\mathbb{Q}\) & \(\times\) & \(0\) \\
\hline
\(\mathbb{R}\) & \(\times\) & \(0\) \\
\hline
\end{tabular}
\end{center}
除非您确实想要获取所有用户列表,否则这可能就是您希望数据结构的样子。如果是这样,您可以在显示订户数量的TextView内显示订户列表的大小。