Clasificación de descripción de datos de Firebase en Android

Estoy almacenando datos en el almacenamiento de Firebase.

Objeto Comment con atributo timestamp . Cuando envío datos desde el dispositivo a Firebase, estoy rellenando la timestamp con currentTime y la almacena en long tipo de datos long .

Cuando firebaseRef.orderByChild("timestamp").limitToLast(15) los datos con firebaseRef.orderByChild("timestamp").limitToLast(15) resultado no está ordenando cómo esperaba.

Incluso jugué con reglas y sin resultado:

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

Probé la timestamp de timestamp tienda en String tipo de datos String , el mismo problema.

Firebase puede ordenar los elementos en orden ascendente por una propiedad determinada y luego devuelve los primeros N elementos ( limitToFirst() ) o los últimos N elementos ( limitToLast() ). No hay forma de indicar que desea los elementos en orden descendente.

Hay dos opciones para obtener el comportamiento que desea:

  1. Utilice una consulta de Firebase para obtener los datos correctos, luego vuelva a pedirlo en el lado del cliente

  2. Agregue un campo que tenga un valor descendente a los datos

Para este último enfoque, es común tener una marca de tiempo invertida.

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

una buena solución que encuentro si estás usando la vista de reciclador para renderizar esa información …

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

invertirá la representación de datos …

 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); 

He resuelto el problema extendiendo FirebaseListAdapter y reemplazando el método 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)); } 

}

No veo ninguna opción para invertir los datos. Pero una manera Brute es obtener los datos.

 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(); } 

El enfoque @Monet_z_Polski, basado en

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

tiene un efecto extraño al no actualizar FirebaseRecyclerView automáticamente (PopulateViewHolder no se activa en cambios en tiempo real). Entonces, la mejor opción es usar una clave negativa para indexar los datos .

Ordenar por el lado del cliente es simple y no requiere más recursos del sistema. Cada instantánea de datos tiene el campo previousChildkey. Si desea clasificar los desc, imagine que la clave anterior de Children es nextChildKey. Aquí está mi muestra:

 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); } } } 

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 }) 

La clasificación de elementos secundarios por TIMESTAMP se puede hacer usando 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 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 también se puede usar con RecyclerView