Android中的Firebase数据描述排序

我将数据存储在Firebase存储中。

具有属性timestamp对象Comment 。 当我将数据从设备推送到Firebase时,我使用currentTime填充timestamp并以long数据types存储。

当我使用firebaseRef.orderByChild("timestamp").limitToLast(15)检索数据时firebaseRef.orderByChild("timestamp").limitToLast(15)结果没有按我的预期排序

我甚至玩过规则而没有结果:

 { "rules": { ".read": true, ".write": true, ".indexOn": "streetrate", "streetrate": { ".indexOn": ".value" } } } 

我尝试在String数据types中存储timestamp ,同样的问题。

  • 与Firebase相关的Google Play服务更新后,Android Google Cloud Messaging(GCM)令牌生成崩溃
  • 如何解决谷歌播放服务错误
  • 程序types已存在:android.support.v13.view.DragAndDropPermissionsCompat
  • Firebase云消息传递API密钥
  • Firebase runloop(3.0.0)中未捕获的exception
  • 如何使用java / android从Firebase ONCE读取数据?
  • 错误:条目中的空值:streamOutputFolder = null
  • 序列化为字节数组会引发IOException(绝不应该发生)
  • Firebase可以按给定属性按升序对项目进行排序,然后返回前N个项目( limitToFirst() )或最后N个项目( limitToLast() )。 没有办法表明您希望项目按降序排列。

    有两种方法可以获得您想要的行为:

    1. 使用Firebase查询获取正确的数据,然后在客户端重新排序

    2. 添加具有降序值的字段到数据

    对于后一种方法,通常具有反转的时间戳。

     -1 * new Date().getTime(); 

    如果您使用Recycler视图呈现该数据,我会发现一个很好的解决方案……

     mLayoutManager = new LinearLayoutManager(getActivity()); mLayoutManager.setReverseLayout(true); mLayoutManager.setStackFromEnd(true); // And set it to RecyclerView mRecyclerView.setLayoutManager(mLayoutManager); 

    它将扭转数据呈现…

     private static class ChatMessageViewHolder extends RecyclerView.ViewHolder { TextView messageText; TextView nameText; public ChatMessageViewHolder(View itemView) { super(itemView); nameText = (TextView)itemView.findViewById(android.R.id.text1); messageText = (TextView) itemView.findViewById(android.R.id.text2); } } FirebaseRecyclerViewAdapter adapter; ref = new Firebase("https://.firebaseio.com"); RecyclerView recycler = (RecyclerView) findViewById(R.id.messages_recycler); recycler.setHasFixedSize(true); ////////////////////////////////////////////////////////// mLayoutManager = new LinearLayoutManager(getActivity()); mLayoutManager.setReverseLayout(true); mLayoutManager.setStackFromEnd(true); recycler.setLayoutManager(mLayoutManager); ///////////////////////////////////////////////////////// adapter = new FirebaseRecyclerViewAdapter(ChatMessage.class, android.R.layout.two_line_list_item, ChatMessageViewHolder.class, mRef) { public void populateViewHolder(ChatMessageViewHolder chatMessageViewHolder, ChatMessage chatMessage) { chatMessageViewHolder.nameText.setText(chatMessage.getName()); chatMessageViewHolder.messageText.setText(chatMessage.getMessage()); } }; recycler.setAdapter(mAdapter); 

    我通过扩展FirebaseListAdapter并覆盖getItem方法解决了问题:

     public abstract class ReverseFirebaseListAdapter extends FirebaseListAdapter { public ReverseFirebaseListAdapter(Activity activity, Class modelClass, int modelLayout, Query ref) { super(activity, modelClass, modelLayout, ref); } public ReverseFirebaseListAdapter(Activity activity, Class modelClass, int modelLayout, DatabaseReference ref) { super(activity, modelClass, modelLayout, ref); } @Override public T getItem(int position) { return super.getItem(getCount() - (position + 1)); } 

    }

    我没有看到任何反转数据的选项。 但One Brute的方法是获取数据。

     List mList=new ArrayList(); public void onDataChange(DataSnapshot dataSnapshot) { mList.clear(); for(DataSnapshot children: dataSnapshot.getChildren()){ ModelClass modelClass=children.getValue(ModelClass.class); mList.add(modelClass); } Collections.reverse(mList); Adapter.notifyDataSetChanged(); } 

    @Monet_z_Polski方法,基于

     @Override public T getItem(int position) { return super.getItem(getCount() - (position + 1)); } 

    对自动更新FirebaseRecyclerView有一个奇怪的影响(PopulateViewHolder不会在实时更改中触发)。 因此,最好的选择是使用否定键来索引数据

    客户端排序很简单,不需要更多系统资源。 每个数据快照都有previousChildkey字段。 如果你想desc排序,想象previousChildkey是nextChildKey。 这是我的样本:

     class LessonFirebaseArray{ private ArrayList mItems; ... public LessonFirebaseArray() { mItems = new ArrayList<>(); } public int addItem(ObjectModel item, boolean isReverse){ int index; if (item.getPreviousChildKey() != null) { index = getIndexForKey(item.getPreviousChildKey()); if (index < 0) { index = mItems.size(); }else if(index>0 && !isReverse) { index = index + 1; } }else{ index = mItems.size(); } mItems.add(index, item); notifyInsertedListeners(index); return index; } private int getIndexForKey(String key) { int index = 0; for (ObjectModel snapshot : mItems) { if (snapshot.getKey().equals(key)) { return index; } else { index++; } } return -1; } private void notifyInsertedListeners(int index) { if (mListener != null) { mListener.onInserted(index); } } } 

    斯威夫特3:

      let query = firebase.child(YourQueryPath).queryOrdered(byChild: YourQueryChild).queryLimited(toLast: YourLimit) query.observeSingleEvent(of: .value, with: { (snapshot) in // Reverse order here to get top **YourLimit** results in descending order }) 

    可以使用android.support.v7.util.SortedList TIMESTAMP对子项进行排序

      class post{ private Object time; public Object getTime() { return time; } public void setTime(Object time) { this.time = time; } ...//rest code} SortedList data; data = new SortedList(post.class, new SortedList.Callback() { @Override public int compare(post o1, post o2) { Long o1l = Long.parseLong(o1.getTime().toString()); Long o2l = Long.parseLong(o2.getTime().toString()); return o2l.compareTo(o1l); }......//rest code ref.addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { mSwipeRefreshLayout.setRefreshing(true); post p=dataSnapshot.getValue(post.class); data.add(p); }...// rest code 

    android.support.v7.util.SortedList也可以与RecyclerView一起使用