Sort data to RecyclerView based on latest date from Firebase
I am developing an android chat application in which I need to order the conversation details by the date.
As I see in your screenshot, your Date
property is of type String. This means that you cannot call:
.orderByChild("Date")
And expect to behave as it was a Timestamp. When you order String elements, the order that you get is always lexicographically. This means that Strings doesn't consider any sort of numeric values when sorting, especially when it comes to the dates, even if the dates contain numbers, as your first element does:
Date: "30/7/2021"
So using String values when querying your database it's not an option. However, I see you already have a Timestamp
property. Maybe on that property, it was supposed to do the ordering. If that was not the case, I suggest you change the type of the Date
property from String to Timestamp, as explained in my answer from the following post:
- How to save the current date/time when I add new value to Firebase Realtime Database
Now I want to retrieve and show the data on the latest date on my RecyclerView
This means that most likely you need to reverse the order, meaning that all your transactions have to be displayed in your RecyclerView descending. In this case, there are a few options that you have, either on the server or on the client.
Assuming that you have changed the type of your Date
property from String to Timestamp, then you can simply consider storing an inverted Timestamp value like this:
Firebase-root
|
--- transactions
|
--- 1
|
--- Date: 1627714194
|
--- invertedDate: -1627714194
See, the invertedDate
property holds a negative value. Since by default, the elements are ordered ascending, to be able to order the transaction desecendiong, you should simply use:
Query query = nm.orderByChild("invertedDate").limitToFirst(5);
On the other hand, there are some workarounds that can be made to achieve the same thing on the client, as explained in my answer from the following post:
- How to arrange firebase database data in ascending or descending order?
FirebaseRecyclerPagingAdapter - sort list by date
You can use a query to order the items by their timestamp
value
val baseQuery: Query = FirebaseDatabase.getInstance().reference.child("news")
val orderedQuery: Query = baseQuery.orderByChild("timestamp")
This will give you the items in ascending order, so you will have to reverse them in your application code.
If you don't want to do that, consider storing an inverted timestamp value in your data:
"news" : {
"-MXJ0Fbmvewl3zZ6-Ugn" : {
"timestamp" : 1617108780000,
"inverted_timestamp" : -1617108780000,
"description" : "A Red Bull tem a ......Continue lendo",
"id" : "-MXJ0Fbmvewl3zZ6-Ugn",
"thumb" : "https://cdn-1.motorsport.com/images/amp/YpNW51X0/s6/formula-1-bahrain-gp-2021-max--2.jpg",
"title" : "F1: Red Bull deve estar ainda melhor na etapa de Ímola; saiba mais",
"url" : "http://motorsport.uol.com.br/f1/news/f1-red-bull-deve-estar-ainda-melhor-em-imola-entenda-os-detalhes/5991023/?utm_source=RSS&utm_medium=referral&utm_campaign=RSS-ALL&utm_term=News&utm_content=br"
},
"-MXJ0LxzjUjfGFDvamKE" : {
"timestamp" : 1617118680000,
"inverted_timestamp" : -1617118680000,
"description" : "As mudanças nas ...Continue lendo",
"id" : "-MXJ0LxzjUjfGFDvamKE",
"thumb" : "https://cdn-1.motorsport.com/images/amp/YBeqJen2/s6/lance-stroll-aston-martin-amr2.jpg",
"title" : "Análise técnica: entenda como as equipes de F1 responderam ao desafio do assoalho de 2021",
"url" : "http://motorsport.uol.com.br/f1/news/analise-tecnica-entenda-como-as-equipes-de-f1-responderam-ao-desafio-do-assoalho-de-2021/5992503/?utm_source=RSS&utm_medium=referral&utm_campaign=RSS-ALL&utm_term=News&utm_content=br"
},
}
With the above data structure, you can then get them items in descending order with:
val orderedQuery: Query = baseQuery.orderByChild("inverted_timestamp")
You can then pass the orderedQuery
to the adapter, to see the items based on their descending timestamp.
How to sort my RecyclerView according to date and time
Change make following changes to your AppointmentData
public class AppointmentData {
// ...
private Object date;
// ...
public void setDate(Object date) {
this.date = date;
}
// ...
public AppointmentData(String name, String tel, String address, String time, Object date) {
// ...
}
// ...
public Object getDate() {
return date;
}
}
Change db to this:
Query db = FirebaseDatabase.getInstance().getReference().child("Email").child(mCurrentUser.getUid()).child("Appointment").orderByChild("date");
Change this line inside populateViewHolder to this: viewHolder.dateApp.setText(timestampToDateString(model.getDate()));
where timestampToDateString is a utility method:
public static String timestampToDateString(long timestamp){
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");
Date date = new Date(timestamp);
return dateFormat.format(date);
}
change btnSave.onClickListener to this
final String key = FirebaseDatabase.getInstance().getReference().child("Email").child(mCurrentUser.getUid()).child("Appointment").push().getKey();
// ...
Long date = mSelectedDate;
// ...
AppointmentData appointmentData = new AppointmentData(name, tel, address, time, date);
FirebaseDatabase.getInstance().getReference().child("Email").child(mCurrentUser.getUid()).child("Appointment").child(key).setValue(appointmentData);
// ...
add the field like so
private long mSelectedDate;
initialize it in datePic() like so
// ...
mYear = c.get(Calendar.YEAR);
// ...
mSelectedDate = fieldToTimestamp(mYear, mMonth, mDay);
and in onDateSelectedListener.onDateSet(...) like so
// ...
mSelectedDate = fieldToTimestamp(year, monthOfYear, dayOfMonth);
where fieldToTimestamp is helper method
private long fieldToTimestamp(int year, int month, int day) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, year);
calendar.set(Calendar.MONTH, month);
calendar.set(Calendar.DAY_OF_MONTH, day);
return (long) (calendar.getTimeInMillis() / 1000L);
}
I think that should be all of it.. Oh, and delete all your old Appointments so it doesn't cause exceptions.
Guaranteed order of fetched data from Firebase Realtime Database
What is the order of data when I fetch from my Firebase Realtime Database without using any orderBy methods?
If you are looking to have your elements ordered even if you don't use a call to orderBy()
, then you should use the pushed IDs provided by the DatabaseReference#push() method. These pushed IDs aren't actually timestamps but they contain a time component. As Michael Lehenbauer mentioned in this blog article:
Push IDs are string identifiers that are generated client-side. They are a combination of a timestamp and some random bits. The timestamp ensures they are ordered chronologically, and the random bits ensure that each ID is unique, even if thousands of people are creating push IDs at the same time.
And to answer your second question:
If I use the get(), is it always 100% guaranteed that the data I will get is sorted from oldest to the newest or will it be in lexicographical order?
It doesn't matter if you add a ValueEventListener or ChildEventListener or even if you call Query#get(), the results will be ordered in the same way.
However, if you need to explicitly have an order according to a time component, then you should add a property of type "timestamp", as explained in my answer from the following post:
- How to save the current date/time when I add new value to Firebase Realtime Database
If you want to reverse the order please check the following answer:
- Sort data to RecyclerView based on latest date from Firebase
Related Topics
How to Call a Restful Web Service from Android
Android What Is Wrong with Openfileoutput
What Optimizations How to Expect from Dalvik and the Android Toolchain
What Is the Use of System.In.Read()
Differencebetween Unidirectional and Bidirectional JPA and Hibernate Associations
How to Send Put, Delete Http Request in Httpurlconnection
How to Change Color of Hamburger Icon in Material Design Navigation Drawer
How to Allow Users to Check for the Latest App Version from Inside the App
Get Filepath and Filename of Selected Gallery Image in Android
Android Room Database: How to Handle Arraylist in an Entity
Access Resource Files in Android
How to Implement a Fileobserver from an Android Service
How to Get Data from Each Dynamically Created Edittext in Android