I have 5 elements in RecyclerView(elements taken from DB) with dates and texts. Two different lists. For dates and for strings. One fragment contains 1 date and 1 string text. So, im need to sort elements by date, like that
Result which i want
text1 10.09.2021
text2 13.09.2021
text3 30.09.2021
text4 1.12.2021
Result which i have
text3 30.09.2021
text4 1.12.2021
text1 10.09.2021
text2 13.09.2021
texts and dates is a two different Lists
The question is, how i can sort dates as strings(may be?) with no text loss, and where im supposed to do that (after getting from db and before retrieve data in adapter? or after loading elements in adapter and then getting them back for sort (looks bad)
thats how im get data from DB and retrieve in adapter
List<String> reminder = new ArrayList<>();
List<String> date = new ArrayList<>();
Calendar test = Calendar.getInstance();
long pars = test.getTimeInMillis();
System.out.println(pars);
dbf.child("Reminders").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
reminder.clear();
date.clear();
for(DataSnapshot child2 : snapshot.getChildren()) { // getting a data from DB to ArrayList for dropping into Adapter
for(DataSnapshot tChild : child2.getChildren()) {
if (tChild.getKey().equals("text")) {
reminder.add(tChild.getValue().toString());
rem = reminder.toArray(new String[reminder.size()]);
}
if (tChild.getKey().equals("date")) {
date.add(tChild.getValue().toString());
dat = date.toArray(new String[date.size()]);
}
}
mainRowAdapter rAdapter = new mainRowAdapter(MainActivity.this, rem,dat);
rv.setAdapter(rAdapter);
rv.setLayoutManager(new LinearLayoutManager(MainActivity.this));
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
setText in AdapterClass
holder.reminder.setText(reminder[position]);
holder.date.setText(date[position]);
in another topic i saw this one, but this cannot help me in my situation? may be some analogies exist?
Collections.sort(categories, new Comparator<Categories>() {
#Override
public int compare(Categories lhs, Categories rhs) {
return lhs.title.compareTo(rhs.title);
}
});
the best place to sort your data is when you get your data from db by a query, but if you want to do it manually on your list the best format for saving your date is like this:
2021.09.10
2021.09.13
2021.09.30
2021.12.01
because string sort can apply to your date.
To sort the dates in descending order, you can simply use:
collections.reverseorder();
Related
Im getting an object from firebase, and there are two ways how i can get object
this one
text1
15.10.2021
text3
12.10.2021
text2
29.11.2021
text4
1.1.2022
or this one
{text = text1 , date = 15.10.2021}
{text = text3 , date = 12.10.2021}
{text = text2 , date = 29.11.2021}
{text = text4 , date = 1.1.2022}
I am need to sort this object by dates like that
text3 12.10.2021
text1 15.10.2021
text2 29.11.2021
text4 1.1.2022
I'm trying to add all into list but I don't know how to sort them.
in list it looks like this
[text1, 15.10.2021, text3, 12.10.2021, text2, 29.11.2021, text4, 1.1.2022]
Im doing that for RecyclerView, and initially im getting dates and strings from Firebase like that
List<String> reminder = new ArrayList<>();
List<String> date = new ArrayList<>();
dbf.child("Reminders").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
reminder.clear();
date.clear();
for(DataSnapshot child2 : snapshot.getChildren()) { // getting a data from DB to ArrayList for dropping into Adapter
for(DataSnapshot tChild : child2.getChildren()) {
if (tChild.getKey().equals("text")) {
reminder.add(tChild.getValue().toString());
rem = reminder.toArray(new String[reminder.size()]); // rem = String[]
}
if (tChild.getKey().equals("date")) {
date.add(tChild.getValue().toString());
dat = date.toArray(new String[date.size()]); // dat = String[]
}
}
mainRowAdapter rAdapter = new mainRowAdapter(MainActivity.this, rem,dat);
rv.setAdapter(rAdapter);
rv.setLayoutManager(new LinearLayoutManager(MainActivity.this));
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
and then in Adapter class im use method setText()
so, the question in the top
Your dates are stored as strings in a format that is unfortunately not chronologically sortable. If you want to sort on dates, I recommend storing them in ISO-8601 format, such as "2021-10-15" so that their lexicographical order matches their chronological order.
Once you have that format, you can retrieve the nodes from the database in the correct order with:
DatabaseReference reminders = dbf.child("Reminders");
Query remindersByDate = reminders.orderByChild("date");
remindersByDate.addValueEventListener(...
Also see:
Firebase sort by points depending on date
Firebase endAt() not working with date string?
Querying by range in firebase
I have a database something like this. How I want to compare the value for all users to get most value.
restaurant
-userUid
-stateUid
-restaurantUid
-price = 9
-restaurantUid2
-price = 10
-stateUid2
-restaurantUid3
-price = 2
As you can see the database there, stateUid price is 19 while stateUid2 price is only 2
So, stateUid has the most price. How to compare them and display the most one. Thank you
EDIT:
I have done something like this, and it's error at return. And the value is not working.
exports.calculateTotal = functions.database.ref('/restaurant/{userUid}/{stateUid}/{restaurantUid}')
.onWrite((change, context) => {
// Only edit data when it is first created.
if (change.before.exists()) {
return null;
}
// Exit when the data is deleted.
if (!change.after.exists()) {
return null;
}
//Get id
const restaurantUid = context.params.restaurantUid;
let totalValue = 0;
change.after.forEach(function (item) {
totalValue += item.child('total').val();
});
console.log(totalValue);
return functions.database.ref('/priceTotal/' + restaurantUid).child('total').set(totalValue);
});
Firebase queries work on a flat list of nodes. A query can contain only a single unknown key, the key of the direct child nodes under the location where you query. In your data structure there are multiple levels of unknown keys, which means that you can't query for the highest price across all of them.
What you can do in your current data structure is query across one state for the restaurant with the highest price. That'd look something like:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("restaurant");
DatabaseReference stateRef = ref.child("userUid").child("stateId");
stateRef.orderByChild("price").limitToLast(1).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot: dataSnapshot.getChildren()) {
Log.i(TAG, snapshot.getKey()+": "+snapshot.child("price").getValue(Long.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
But you can't search across all states for a user, or even all users. If you want to allow that, you'll have to store all prices in a flat list, like:
restaurant_prices: {
"restaurantid": {
price: 9,
state: "statid",
user: "userid"
}
}
Also see:
Firebase Query Double Nested
Firebase query if child of child contains a value
int totalPrice = 0;
int greaterPrice = 0;
int temp = 0;
DatabaseRefernce restRef = FirebaseDatabase.getInstance().getReference().child("restaurant").child(userUid);
restRef.addValueEventListener(new ValueEventListener(){
onDataChange(Datasnapshot snapshot) {
for(Datasnapshot snap : snapshot) {
String key = snap.getKey();
//This will return you the keys of stateUid
restRef.child(key).addValueEventListener(new ValueEventListener(){
onDataChanged(DatSnapshot datasnapshot) {
//this for loop will iterate through restaurants of that specific state
for(DataSnapshot snap2 : datasnapshot){
totalPrice += (int) snap2..child("price").getValue();
}
//When this loop ends you will get the total price of all restaurants from that state
}
});
//as u see above I mentioned greater price and temp variable
using simple logic of finding greatest number out of two number save the value of greatest integer to the variable every time you loop through state
}
}
}
);
Use nested for loops to iterate from database like above and calculate your prices
Else what you can do is when you are uploading the data of restos - while uploading prices just make an extra node for total price of city and add price of resto every time you upload new resto
Hi I am trying to populate recycler view by getting data from two different nodes in firebase. However I am getting two separate listings... one of each node. I want to combine them and show as a single item. My original question is posted here if more files are required to be seen : Populating Recycler View From Nested Queries in Firebase
My Fragment is as follows
// Firebase
fbDatabaseRootNode = FirebaseDatabase.getInstance().getReference();
fbDatabaseRefGroupList = fbDatabaseRootNode.child("groups_list").child(current_user_id);
fbDatabaseRefGroups = fbDatabaseRootNode.child("groups");
fbDatabaseRefGroupList.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// Array to Get Group List
lGroupsList = new ArrayList<>();
if (dataSnapshot.exists()) {
// Clear Array to Get Group List
lGroupsList.clear();
for (DataSnapshot glSnapshot : dataSnapshot.getChildren()) {
// Use The Model To Format Array List and Pass It Into It
GroupsListModel g = glSnapshot.getValue(GroupsListModel.class);
// Array to Get Group List
lGroupsList.add(g);
// Get The Group ID To Get Data From Other Nodes
String groupID = String.valueOf(glSnapshot.getKey());
fbDatabaseRefGroups.child(groupID).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
// Array to Get Group List
lGroupsList2 = new ArrayList<>();
if (dataSnapshot.exists()) {
// Clear Array to Get Group List
lGroupsList2.clear();
// String groupName = (String) dataSnapshot.child("group_name").getValue();
// String groupTagLine = (String) dataSnapshot.child("group_tagline").getValue();
// String groupMemberCount = (String) dataSnapshot.child("group_member_count").getValue();
// Use The Model To Format Array List and Pass It Into It
GroupsListModel g = dataSnapshot.getValue(GroupsListModel.class);
// Array to Get Group List
lGroupsList2.add(g);
// Joining The Arrays To Get One Array
lGroupsList.addAll(lGroupsList2);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
aGroupList = new GroupsListAdapter(getContext(), lGroupsList);
rvGroupList.setAdapter(aGroupList);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
However the problem seems to be that instead of joining the two nodes to show the item as one, I am getting two items in the list (first one containing data from lGroupsList and second one from lGroupsList2). They do not seem be joining.
// Joining The Arrays To Get One Array
lGroupsList.addAll(lGroupsList2);
I have a firebase database that has a name and number in it for each of my stores. I want a spinner to show the names of each store so we can select one. the store name example is "0023 franklin", and i want to order them by the number.
my code to make the spinner is
mydb.orderByValue().addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Is better to use a List, because you don't know the size
// of the iterator returned by dataSnapshot.getChildren() to
// initialize the array
final List<String> areas = new ArrayList<String>();
for (DataSnapshot areaSnapshot: dataSnapshot.getChildren()) {
Store storeName = areaSnapshot.getValue(Store.class);
areas.add(storeName.getStoreName());
}
Spinner areaSpinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter<String> areasAdapter = new ArrayAdapter<String>(checkout.this, android.R.layout.simple_spinner_item, areas);
areasAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
areaSpinner.setAdapter(areasAdapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
it shows all the stores but doesn't order them by the number. and the stores are not added in the database in order.
how to i make this happen?
adding JSON
storelist:
-KvIoZC0AbpD1-SJJrIS
faxNum: 987654321
storeName: 0024 Franklin
-KvIobgHLouocLpMkN6k
faxNum: 1234567890
storeName: 0003 Randle
You can use any of the following methods to sort the data:
orderByChild()
orderByValue()
orderByKey()
You can store that number with a key like 'storeNumber' and use the available method like:
orderByChild("storeNumber");
for more usage refer to :
https://firebase.google.com/docs/database/android/lists-of-data?authuser=0#sort_data
I am building recipes app. I have page in my app that retrieves all the recipes from the database on Firebase into ListView. Each Recipe has these variables:
public String key;
public String uid;
public String title;
public String type;
public String ingredients;
public String instructions;
public int likes;
Here's the function that retrieves all the data :
//Retrieve Data from database
public void retriveData() {
database.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
recipes = new ArrayList<Recipe>();
for(DataSnapshot data : dataSnapshot.getChildren()) {
Recipe r = data.getValue(Recipe.class);
recipes.add(r);
}
allRecipeAdapter = new AllRecipeAdapter(AllRecipeActivity.this,0,0,recipes);
lv.setAdapter(allRecipeAdapter);
}
}
}
Now i want to create another screen that also has a ListView and i would like to sort the Recipes by nubmer of likes and then enter the top 10 recipes into the ListView.
I searched on Google i found the function OrderByValue but i can't figure out how to use it i realized how to works but i can't implement this to my project.
Gaƫtan Maisse and KLHauser gave you solutions that work in pure client-side code. Here's an alternative that uses Firebase Database queries, which means the ordering and filtering happen on the server:
// assuming that database refers to the list of all recipe
Query topRecipes = database.orderByChild("likes").limitToLast(10);
topRecipes.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
recipes = new ArrayList<Recipe>();
for(DataSnapshot data : dataSnapshot.getChildren()) {
Recipe r = data.getValue(Recipe.class);
// add the recipe to the front of the list
recipes.add(0, r);
}
allRecipeAdapter = new AllRecipeAdapter(AllRecipeActivity.this,0,0,recipes);
lv.setAdapter(allRecipeAdapter);
}
}
Since Firebase queries always sort items in ascending order, the query takes the last 10 items - those are the ones with the highest like count. To reverse those items, the code inserts each item to the from of the list, instead of appending them to the end.
You can sort your list using a Comparator and then get a sublist of 10 first elements before displaying it in the ListView:
Comparator<Recipe> likesOrderComparator = new Comparator<Recipe>() {
public int compare(Recipe recipe1, Recipe recipe2) {
return recipe1.likes < recipe2.likes ? -1 : recipe1.likes == recipe2.likes ? 0 : 1;
}
};
Collections.sort(recipes, likesOrderComparator);
List<Recipe> topTenRecipes = recipes.subList(0, 9);
// Now display topTenRecipes in a ListView
Java7:
Collections.sort(list, new Comparator<Recipe>() {
#Override
public int compare(Recipe r1, Recipe r2) {
if (r1.getLikes() > r2.getLikes())
return 1;
if (r1.getLikes() < r2.getLikes()
return -1;
return 0;
}
});
Java8 (using lambda):
recipes.stream()
.sorted((r1, r2) -> Integer.compare(r1.getLikes(),
r2.getLikes()))