要指出问题,让我们假设我们有HackerNews饲料,我们听听Firebase中的“posts”对象.
当然,在我们的应用程序中有RecyclerView显示帖子,我认为最好的主意是使用FirebaseUI,但问题是我们希望在更改服务器端或测试时使用更抽象的应用程序.所以我们会使用一些适配器,但这是另一个question.
我提到两个听众,问题是哪个更好?
当我们使用ValueEventListener时,我们将获得整个集合,但是如果有任何变化,像一个用户改变了内容,我们将不得不重新加载整个数据,这意味着更多的字节通过昂贵的网络传输发送.另一个问题是当我们使用多用户时,这里是例子:
> Post有userId,但是我们要显示他的名字,所以在onDataChanged方法中,我们获取了用户数据,如下所示:
postsReference.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for (DataSnapshot data : dataSnapshot.getChildren()) { Post post = data.getValue(Post.class); usersReference.child(post.getUserId()).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { // Here we have user data } @Override public void onCancelled(FirebaseError firebaseError) { } }); } } @Override public void onCancelled(FirebaseError firebaseError) { } });
您可以看到,现在我们必须单独添加每个帖子到RecyclerView,这将给我们提示,也许我们应该使用ChildEventListener.
所以现在当我们使用ChildEventListener时,问题是一样的 – 我们必须将每个帖子分别添加到RecyclerView中,但是当有人更改帖子内容时,firebase只会发送给我们这个帖子,这意味着通过网络减少数据.
我们不喜欢单独添加post RecyclerView,因为例如:
– 很难添加加载指示器,因为我们不知道所有数据何时出现.
– 用户不断刷新视图,而新帖子而不是整个列表变得可见.
– 很难对该集合进行排序,我们必须在适配器中执行此操作.
题
使用firebase收集的最佳做法是什么,也可能比上面写的更好的解决方案?
编辑
数据方案将如下所示:
"posts" : { "123456" : { "createdAt" : 1478696885622,"content" : "This is post content","title" : "This is post title","userId" : "abc" },"789012" : { "createdAt" : 1478696885622,"content" : "This is post content 2","title" : "This is post title 2","userId" : "efg" } } "users" : { "abc" : { "name" : "username1" },"efg" : { "name" : "username2" } }
编辑2
我犯了一个错误 – >当事情发生变化时,Firebase不会在ValueEventListener中获取整个数据.它只得到“三角洲”,here是证明.
解决方法
> ChildEventListener通常是同步对象列表的推荐方式.这甚至在documentation on working with lists中提到:
When working with lists,your application should listen for child events rather than the value events used for single objects.
这是因为您的客户端仅接收具有特定更新(添加或删除)的已更改子项,而不是每次更新时的整个列表.因此,它允许更精细地处理列表的更新.
> ValueEventListener可以更有用,当您需要处理整个列表修改一个孩子.当您必须对RecyclerView中的列表进行排序时,就是这种情况.通过获取整个列表,对其进行排序并刷新视图的数据集,这样做更容易.另一方面,使用ChildEventListener,更难进行排序,因为只能在每个更新事件的列表中访问一个特定的子节点.
从性能的角度来看,鉴于即使ValueEventListener在同步更新时也意识到“增量”,所以我认为它在客户端方面效率较低,因为客户端必须对整个列表,但这还远远优于网络方面的低效率.
关于持续刷新和进度指标,最重要的是要注意的是,Firebase数据库是一个实时数据库,因此实时数据的不断提供是固有的特征.如果不需要更新事件,您只需使用addListenerForSingleValueEvent方法只读取一次数据.如果要在加载第一个快照时显示进度指示器,也可以使用此选项:
// show progress indicator postsReference.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { // load initial data set // hide progress indicator when done loading } ... });