Je stocke des données dans le stockage Firebase.
Objet Comment
avec attribut timestamp
. Lorsque je transfère des données d'un périphérique à Firebase, je remplis timestamp
avec currentTime et le stocke dans le type de données long
.
Lorsque je récupère les données avec firebaseRef.orderByChild("timestamp").limitToLast(15)
, le résultat ne correspond pas à mes attentes.
J'ai même joué avec des règles et aucun résultat:
{
"rules": {
".read": true,
".write": true,
".indexOn": "streetrate",
"streetrate": {
".indexOn": ".value"
}
}
}
J'ai essayé de stocker timestamp
dans le type de données String
, même problème.
Firebase peut classer les éléments dans l'ordre croissant d'une propriété donnée, puis renvoie les N premiers éléments (limitToFirst()
) ou les N derniers éléments (limitToLast()
). Il n'y a aucun moyen d'indiquer que vous voulez les éléments dans l'ordre décroissant.
Il existe deux options pour obtenir le comportement souhaité:
Utilisez une requête Firebase pour obtenir les données correctes, puis réorganisez-la côté client.
Ajouter un champ ayant une valeur décroissante aux données
Pour cette dernière approche, il est courant d’avoir un horodatage inversé.
-1 * new Date().getTime();
une bonne solution que je trouve si vous utilisez Recycler View pour restituer ces données ...
mLayoutManager = new LinearLayoutManager(getActivity());
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
// And set it to RecyclerView
mRecyclerView.setLayoutManager(mLayoutManager);
il va inverser le rendu des données ...
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);
Je ne vois aucune option pour inverser les données. Mais une façon brute est d'obtenir les données.
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();
}
J'ai résolu le problème en étendant FirebaseListAdapter et en redéfinissant la méthode 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));
}
}
L’approche @Monet_z_Polski, basée sur
@Override
public T getItem(int position) {
return super.getItem(getCount() - (position + 1));
}
n’a pas un effet étrange sur la mise à jour automatique de FirebaseRecyclerView (PopulateViewHolder n’est pas déclenché lors des modifications en temps réel) Donc, la meilleure option est utilisez une clé négative pour indexer les données .
Le tri des éléments enfants par TIMESTAMP peut être effectué à l'aide de 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
Android.support.v7.util.SortedList
peut également être utilisé avec RecyclerView
Le tri côté client est simple et ne nécessite pas plus de ressources système . Chaque instantané de données possède un champ previousChildkey. Si vous voulez faire un tri par ordre décroissant, imaginez que previousChildkey est nextChildKey . Voici mon exemple:
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);
}
}
}
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
})
Si vous le faites sur le Web, vous pouvez alors pousser des valeurs dans un tableau, puis imprimer les valeurs stockées dans l’ordre inverse.
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.
}
}