8

I try to develop a simple shopping application. There will be a few product categories and I use different activity with ListView for every category. When User choose product category (say items1 ="drinks")- new screen opens and he can add "soda", "cola"... I want to add count badge on every category to show number of products per category. So, for example for "items" I need to display 5, for "items1" - 2 and for "items10/11" - display 1:

enter image description here

my ActivityItems1 code:

       private Firebase mRef;
       private String mUserId;
       private String itemsUrl;
       private TextView badge;


       itemsUrl = Constants.FIREBASE_URL + "/users/" + mUserId + "/items1";



    // Set up LisView
    final ListView listView = (ListView) findViewById(R.id.listView);
    final ArrayAdapter<String> adapter = new ArrayAdapter<>(this,     android.R.layout.simple_list_item_1, android.R.id.text1);
    listView.setAdapter(adapter);  

    // Find badge
         badge =(TextView)findViewById(R.id.badgeView);


    // Use Firebase to populate the list.
    new Firebase(itemsUrl)
            .addChildEventListener(new ChildEventListener() {
                @Override
                public void onChildAdded(DataSnapshot dataSnapshot, String   s) {
                    adapter.add((String)     dataSnapshot.child("title").getValue());


     Log.e(dataSnapshot.getKey(),    dataSnapshot.getChildrenCount() + "");

     badge.setText(dataSnapshot.getChildrenCount() + "");
                }

After running the code I received Key and number of his children: E-KJGG2driQ6HJI8R7eve: 1 E-KJGG3Ua6rmlQYn4IHF: 1

it's always 1 child for every Key because Key=Product ID and child of the Key - it's title. But I need to count Keys/ Product IDs (products in category "drinks") and not his children...

user5866501
  • 483
  • 2
  • 5
  • 12
  • You could use a child added and child changed value instead of a value event type, this way you could simply use the dataSnapshot.getChildrenCount() – Ymmanuel Jun 02 '16 at 19:33
  • @YmmanuelFlores `getChildrenCoun()` only makes sense for a value event. Otherwise you simply get a count of the number of properties, which is unlikely to be what OP wants. – Frank van Puffelen Jun 02 '16 at 19:56
  • `badgeView=null` indicates that you haven't initialized `badgeView` and thus it will throw a `NullPointerException` when you call `badgeView.setText()`. You're likely missing a `badgeView = findViewById()` in your `onCreate()` method. – Frank van Puffelen Jun 02 '16 at 19:59
  • @FrankvanPuffelen ... Nope...if you set the reference at the parent of items...items1....items10...etc and use the child_added..in each event he would receive a snapshot for each event..(the key of the first event would be 'items') there he can use the getChildrenCount() that would count the children..(-kj....) and that is what OP wants – Ymmanuel Jun 02 '16 at 20:02
  • @YmmanuelFlores `child_added` fires at the child level, it will *not* fire for the parent. Try it. – Frank van Puffelen Jun 02 '16 at 20:11
  • @FrankvanPuffelen as you suggested i tried it and as I said it worked.... I posted the answer so you can try it to. ;) – Ymmanuel Jun 02 '16 at 20:42
  • Ah.... now I get it. It's a multi-level hierarchy. I completely overlooked that. Good catch, upvoted. – Frank van Puffelen Jun 02 '16 at 21:17
  • @FrankvanPuffelen - you're right, I forgot to initialize badgeView. But after I did this - still my TextView / badgeView is empty... `private TextView badge; badge =(TextView)findViewById(R.id.badgeView);` – user5866501 Jun 02 '16 at 22:12
  • @FrankvanPuffelen - and my XML: ` ` – user5866501 Jun 02 '16 at 22:17
  • Firebase has recently released Cloud Functions. Have a look at this [answer](http://stackoverflow.com/a/42713792/5861618) for more details – Rosário Pereira Fernandes Mar 10 '17 at 08:55

2 Answers2

27

Databse Reference

With this Database you have two options:

1)Use Child Added

FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference();
//You must remember to remove the listener when you finish using it, also to keep track of changes you can use the ChildChange
myRef.addChildEventListener(new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
        Log.e(dataSnapshot.getKey(),dataSnapshot.getChildrenCount() + "");
    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String s) {

    }

    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {

    }

    @Override
    public void onChildMoved(DataSnapshot dataSnapshot, String s) {

    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

2)Use the Value listener

FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference();

//You can use the single or the value.. depending if you want to keep track
thismyRef.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot snap: dataSnapshot.getChildren()) {
            Log.e(snap.getKey(),snap.getChildrenCount() + "");
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

Here is the output for both cases

enter image description here

If you need to keep constant tracking is best to use the Child events...because otherwise each time anything changes you will receive the entire json over the network, instead of only the portion of information that was changed

If you need a snapshot only once, you better use the singleValue since this way you will receive all the information at the same time

Ymmanuel
  • 2,523
  • 13
  • 12
  • This answer was made using the new Firebase 3....if you are still using the legacy version and you cannot migrate...the solution will still work the only thing that changes is the way you get your database reference as established here https://firebase.google.com/support/guides/firebase-android#fix_your_class_references_numbered – Ymmanuel Jun 02 '16 at 20:54
  • I'll try and post my comment after. Thank you! – user5866501 Jun 02 '16 at 20:57
  • I tried the 2nd approach and my code looks now like this: `new Firebase(itemsUrl).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { ... badge.setText((int) snap.getChildrenCount() + ""); ` and still can't see the count on badge...I feel like I do some stupid syntax mistake - but can't figure it out... – user5866501 Jun 02 '16 at 22:28
  • Ymmanuel, It seems like I didn't explain clear enough my situation. I have **different activities for different items**: one for "items", second for "items1"... ("item"&"item1"= product categories: dairy, drinks...) And when I tried to implement ChildAdded approach - I received Key and number of his children -**it's always 1 child for every Key in this case because Key=Product ID and child of the Key - it's title**). But I need to count Product IDs (products in category) and not his children. – user5866501 Jun 03 '16 at 16:28
  • In SQL it should be: Select count (Key/ProductID) from items; select count (Keys) from items1 etc. So for "items" in first activity I receive 5, for “items1” – 2. I’ll very appreciate for any help! – user5866501 Jun 03 '16 at 16:30
  • so items, items1..etc are categories like drinks, dairy, meat??? and the K... nodes are products like milk, soda, water, wine, etc??? and you want t know how many items are per category? – Ymmanuel Jun 03 '16 at 16:32
  • yes, suppose items1 = drinks category and in this category user can add list: cola, soda... I need to count these drinks for "drink" category/ "items1". So if the user add cola and soda (in Firebase it's 2 different Keys under "items1") - I need to show in TextView "2" – user5866501 Jun 03 '16 at 16:41
  • sure, couple of minutes – user5866501 Jun 03 '16 at 16:43
  • Thank you so much, It returns what i expected. – ʍѳђઽ૯ท Apr 05 '17 at 21:07
  • I'm not sure if it were mentioned, but your solution gets the count of everything. If we need to the count of something specific. How does that work? At least in my situation I can't seem to figure out how to get just a single child's count. – wesley franks Jul 10 '19 at 22:07
1

I'm not sure about that but It can couse of parsing. Try to

badgeView.setText(nums+"");

maybe It could help.

Rıdvan
  • 720
  • 7
  • 11