Android中的Firebase数据描述排序

Android中的Firebase数据描述排序,android,firebase,sorting,firebase-realtime-database,Android,Firebase,Sorting,Firebase Realtime Database,我正在Firebase存储中存储数据 对象注释带有属性时间戳。当我将数据从设备推送到Firebase时,我用currentTime填充时间戳,并存储在long数据类型中 当我使用firebaseRef.orderByChild(“timestamp”).limitToLast(15)检索数据时,结果没有按照我的预期排序 我甚至玩弄规则,但没有结果: { "rules": { ".read": true, ".write": true, ".

我正在Firebase存储中存储数据

对象
注释
带有属性
时间戳
。当我将数据从设备推送到Firebase时,我用currentTime填充
时间戳
,并存储在
long
数据类型中

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

我甚至玩弄规则,但没有结果:

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

我尝试将
时间戳
存储在
字符串
数据类型中,问题相同。

Firebase可以按给定属性按升序排序项目,然后返回前N个项目(
limitToFirst()
)或最后N个项目(
limitToLast()
)。没有办法表明您希望项目按降序排列

有两个选项可以获得您想要的行为:

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

  • 向数据中添加具有降序值的字段

  • 对于后一种方法,通常使用反转的时间戳

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

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

    public abstract class ReverseFirebaseListAdapter<T> extends FirebaseListAdapter<T>  {
    
    public ReverseFirebaseListAdapter(Activity activity, Class<T> modelClass, int modelLayout, Query ref) {
        super(activity, modelClass, modelLayout, ref);
    }
    
    public ReverseFirebaseListAdapter(Activity activity, Class<T> modelClass, int modelLayout, DatabaseReference ref) {
        super(activity, modelClass, modelLayout, ref);
    }
    
    @Override
    public T getItem(int position) {
      return super.getItem(getCount() - (position + 1));
    }
    
    公共抽象类ReverseFirebaseListAdapter扩展FirebaseListAdapter{
    公共ReverseRefRebeSelistAdapter(活动活动、类modelClass、int modelLayout、查询引用){
    超级(活动、模型类、模型布局、参考);
    }
    public ReverseRefRebeSelistAdapter(活动活动、类modelClass、int modelLayout、数据库参考ref){
    超级(活动、模型类、模型布局、参考);
    }
    @凌驾
    公共T getItem(内部位置){
    返回super.getItem(getCount()-(位置+1));
    }
    

    }基于

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

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

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

    class LessonFirebaseArray<ObjectModel>{
    
      private ArrayList<ObjectModel> 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);
        }
      }
    }
    
    类LessonFirebaseArray{
    私有数组列表;
    ...
    公共课FirebaseArray(){
    mItems=新的ArrayList();
    }
    public int addItem(ObjectModel项,布尔值为everse){
    整数指数;
    if(item.getPreviousChildKey()!=null){
    index=getIndexWorkey(item.getPreviousChildKey());
    如果(指数<0){
    index=mItems.size();
    }否则如果(索引>0&!isReverse){
    指数=指数+1;
    }
    }否则{
    index=mItems.size();
    }
    添加(索引,项目);
    notifyInsertedListeners(索引);
    收益指数;
    }
    私有int GetIndexWorkey(字符串键){
    int指数=0;
    用于(对象模型快照:mItems){
    if(snapshot.getKey().equals(key)){
    收益指数;
    }否则{
    索引++;
    }
    }
    返回-1;
    }
    私有void notifyInsertedListeners(int索引){
    if(mListener!=null){
    mListener.onInserted(索引);
    }
    }
    }
    
    如果您使用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<ChatMessage, ChatMessageViewHolder> adapter;
         ref = new Firebase("https://<yourapp>.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, ChatMessageViewHolder>(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);
    
    私有静态类ChatMessageViewHolder扩展了RecyclerView.ViewHolder{
    文本查看消息文本;
    文本视图名称文本;
    public ChatMessageViewHolder(查看项目视图){
    超级(项目视图);
    nameText=(TextView)itemView.findViewById(android.R.id.text1);
    messageText=(TextView)itemView.findViewById(android.R.id.text2);
    }
    }
    FirebaseRecycleServiceAdapter适配器;
    ref=新火基(“https://.firebaseio.com");
    RecyclerView回收器=(RecyclerView)
    findViewById(R.id.messages\u recycler);
    回收商。setHasFixedSize(真);
    //////////////////////////////////////////////////////////
    mLayoutManager=新的LinearLayoutManager(getActivity());
    mLayoutManager.setReverseLayout(true);
    mLayoutManager.setStackFromEnd(true);
    回收商。setLayoutManager(mLayoutManager);
    /////////////////////////////////////////////////////////
    适配器=新的FirebaseRecycleServiceAdapter(ChatMessage.class,android.R.layout.two\u line\u list\u项,ChatMessageViewHolder.class,mRef){
    public void populateViewHolder(ChatMessageViewHolder ChatMessageViewHolder,chatmessagechatmessage){
    chatMessageViewHolder.nameText.setText(chatMessage.getName());
    chatMessageViewHolder.messageText.setText(chatMessage.getMessage());
    }
    };
    回收商。setAdapter(mAdapter);
    
    我看不到任何反转数据的选项。但一个残酷的方法是获取数据

    List<ModelClass> 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();
    }
    
    List mList=new ArrayList();
    公共void onDataChange(DataSnapshot DataSnapshot)
    {
    mList.clear();
    for(DataSnapshot子项:DataSnapshot.getChildren()){
    ModelClass ModelClass=children.getValue(ModelClass.class);
    mList.add(模型类);
    }
    收款。反向(mList);
    Adapter.notifyDataSetChanged();
    }
    
    Swift 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对子项按时间戳排序

      class post{
    private Object time; 
    
    public Object getTime() {
            return time;
        }
    
    public void setTime(Object time) {
        this.time = time;
    }
                            ...//rest code}
    
    SortedList<post> data;
    
     data = new SortedList<post>(post.class, new SortedList.Callback<post>() {
            @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
    
    class post{
    私有对象时间;
    公共对象getTime(){
    返回时间;
    }
    公共无效设置时间(对象时间){
    这个时间=时间;
    }
    …//rest代码}
    分类列表数据;
    data=new SortedList(post.class,new SortedList.Callback(){
    @凌驾
    公共整数比较(o1后、o2后){
    Long o1l=Long.parseLong(o1.getTime().toString());
    Long o2l=Long.parseLong(o2.getTime().toString());
    将o2l.比较器返回到(o1l);
    }..//rest代码
    ref.addChildEventListener(新的ChildEventListener(){
    @凌驾
    一次CHILDADDED(DATASNAPD)的公共空白
    
    var a=[]; //declaring an array a.
    var num=snapshot.numChildren(); //storing number of children in var num.
    a.push(snapshot.val()); // pushing data in the array.
    if (a.length==num){ //checking if length of array is same as number of children.
    a.reverse(); //reversing the array elements.
    for(i=0; i<num; i++){
    a[i].name;//this will sort the data in descending order.
    }
    }
    
    -3
    -2
    -1
    
    citiesRef.orderBy("name", "desc").limit(3)
    
    FirebaseFirestore.getInstance().collection("leaderboard")
                .orderBy("score")
                .addSnapshotListener { snapshot, exception ->
    
                    if (exception != null) {
                        Log.e("Exception:", "Could not retrieve scores ${exception.localizedMessage}")
                    }
    
                    if (snapshot != null) {
                        scores.clear()
    
                        for (document in snapshot.documents) {
                            val data = document.data
    
                            val name = data?.get("name") as? String
                            val score = data?.get("score") as? Number
    
                            val documentId = document.id
    
                            val newScore = Score(name, score, documentId)
                            scores.add(newScore)
                        }
    
                        scores.reverse()
                        scoresAdapter.notifyDataSetChanged()
                    }
                }
    
    Collections.sort(list, new Comparator<ModuleClass>() {
                        @Override
                        public int compare(ModuleClass module, ModuleClass t1) {
                            return Integer.compare(module.getViews(), t1.getViews());
                        }
                    });
    
    FirebaseDatabase.getInstance().getReference().child("parent_id")
    .child("id").orderByChild("count");
    
        tpDBListener = tpDatabaseRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                tpUploads.clear();
                for(DataSnapshot postSnapshot : snapshot.getChildren()){
                    newUpload pupload = postSnapshot.getValue(newUpload.class);
                    pupload.setKey(postSnapshot.getKey());
                    
                        tpUploads.add(pupload);//add new object on end
                        //tpUploads.add(0,pupload);//add new object at beginning
                    
                }
                tpAdapter.notifyDataSetChanged();
            }
    
            @Override
            public void onCancelled(@NonNull DatabaseError error) {
                Toast.makeText(home.this, error.getMessage(),Toast.LENGTH_SHORT).show();
            }
        });
    
     tpUploads.add(0, pupload);//add new object at beginning
    
    .orderBy("child_ID") 
    
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) 
    {
     desireList.clear();
     List<YourModel>tempList = new ArrayList<>();//Create temp list Object.
    
     for (DataSnapshot dataSnapshotList : dataSnapshot.getChildren()) 
       {
        tempList.add(new YourModel(
           dataSnapshotList.child("Name").getValue() + "",
           dataSnapshotList.getKey() + "",
           dataSnapshotList.child("ORDERBY").getValue() + ""));
       }
           //Save object list in reverse order start.
           for (int i =tempList.size(); i>0; i--)
            {
              desireList.add(tempList.get(i-1));
            }
           //Save object list in reverse order end.
    
            tempList.clear(); //To clear memory only(not required.)
            //Then update your adapter
            yoursAdapter.notifyDataSetChanged();
     }