1

I have a short Question about my Code.

I'm using a recyclerview in my Android App, and fill it with some data out of my Firebase Database.

It works well, but I notice that the ordering is not right :/

I have this Code:

private void getRankings() {
        // hole anzahl an Teilnehmern
        mDatabase.child(TEILNEHMERDATA).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                // hole Anzahl aller Teilnehmer um das Ranking zu bestimmen
                teilnehmerVar = (int) dataSnapshot.getChildrenCount();
                mDatabase.child(TEILNEHMERDATA).orderByChild("score").addChildEventListener(new ChildEventListener() {
                    Teilnehmer teilnehmer = new Teilnehmer();
                    int i = teilnehmerVar+1;
                    @Override
                    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                        // teamname, Platzierung, Punkte
                        int punkteStand = (int) Double.parseDouble(String.valueOf(dataSnapshot.child("score").getValue()));

                        i -= 1;
                        this.teilnehmer = new Teilnehmer(dataSnapshot.getKey(), ((String) dataSnapshot.child("teamname").getValue()), "Platz " + i, punkteStand + " Punkte");
                        teilnehmerList.add(0, this.teilnehmer);     // add to recyclerview: add(0, teilnehmer) gebe in desc aus von 0 zum n. eintrag
                        mAdapter.notifyDataSetChanged();    // save
                    }

In this row:

mDatabase.child(TEILNEHMERDATA).orderByChild("score").addChildEventListener(new ChildEventListener() {

Order Child by score

I get my Data with Structure like this:

"Teilnehmer" : {
    "user_0gPpHXzKqLd2xA" : {
      "image" : "",
      "score" : "0",
      "startnummer" : "1",
      "teamname" : "Andy Foo"
    },

The row score contains an Integer with a Datarange from 0 to ∞

My Layout looks like:

Teamname1    9 Punkte
Platz 1

Teamname2    0 Punkte
Platz 2

Teamname3    1000 Punkte
Platz 3

But its absolutely wrong :/

9 is bigger than 10000 seems my Query order only by the first number

1..2..3..

My Recyclerview initialization:

recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);

Can anyone help me out?

KENdi
  • 7,576
  • 2
  • 16
  • 31
thefab
  • 59
  • 1
  • 11
  • Have you tried to use `orderByValue()` method? – Alex Mamo Jun 19 '17 at 21:31
  • This was a fast reply. Yeah tried with orderByValue().startAt("0").endAt("99999999") but does not work (i do not get anything data) – thefab Jun 19 '17 at 21:34
  • Have you tried to use in stead of this line: `mDatabase.child(TEILNEHMERDATA).orderByChild("score").addChildEventListener(new ChildEventListener() {` this line of code: `mDatabase.child(TEILNEHMERDATA).child(userId).orderByChild("score").addChildEventListener(new ChildEventListener() {`? In which `userId` is the id that see right beneath the `TEILNEHMERDATA` node. – Alex Mamo Jun 19 '17 at 21:57
  • Thanks, it works with integer or double numbers. But i must use an backend (for other people) to manage these data, and these backend store all data elements as a String... can i use the rules validation to cast these string into integer or double value? this could solve my problem as well. I can not change the backend (Web Gui from 3rd party developer) to store these element directly as int / double – thefab Jun 19 '17 at 22:00
  • @AlexMamo TEILNEHMERDATA contains only the Tablename: private String TEILNEHMERDATA = "Teilnehmer"; userID is the firebase authenticaton UID + my prefix user_$UID i will try it with .child(user_$iuid) – thefab Jun 19 '17 at 22:02
  • In this case i see that you are missing a child, `user_0gPpHXzKqLd2xA`. – Alex Mamo Jun 19 '17 at 22:03

2 Answers2

1

If you store values as strings, they will be order lexicographically. To get the wanted order, either store them as numbers or store them in a string that also orders the way you want. E.g.

"Teilnehmer" : {
    "user_0gPpHXzKqLd2xA" : {
      "image" : "",
      "score" : "00000",
      "startnummer" : "1",
      "teamname" : "Andy Foo"
    },
    "user_0gPpHXzKqLd2xB" : {
      "image" : "",
      "score" : "00123",
      "startnummer" : "1",
      "teamname" : "Andy Bar"
    },

So in the above structure when you order on score it will still end up sorted according to the numeric value too. This a common trick, for example you will often see dates formatted as 2017-06-19 since that ensures they order in the correct way for dates (even though the type is a string).

Note that I only recommend doing this because of your back-end system limitation. In most cases, you should simply store numbers as numbers and prevent this workaround.

See:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Ok thanks, is it possible to convert on server (cloud functions) from string to int? So my backend stores data as a string, and any firebase cloud code convert it to valid integer? – thefab Jun 20 '17 at 10:39
0

Use this when creating your recycler view

 LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
 layoutManager.setReverseLayout(true);
 layoutManager.setStackFromEnd(true);
 recyclerView.setLayoutManager(layoutManager)
Martin De Simone
  • 2,108
  • 3
  • 16
  • 30