0

How would I achieve the retrieval of account based arrays, Currently when I run the following code it doesn't retrieve anything. I'm a complete beginner and I tried looking at other examples but mine are different to others. My goal is to retrieve all the arrays belonging to that user. For now I just want to return the names of these items but later I want to to use the array also, So the first user would have:

Fruit = ["apple", "banana", "mango" ]
Veg = ["tomato", "potato", "cabbage" ]

Code:

public class HomeActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener{

private ZXingScannerView scannerView;
private final int permission_code = 1;

String [] selectedProfile;
Spinner spinner;
ArrayAdapter<CharSequence> adapter;

ListView lvProfiles;


private String userID;
private FirebaseDatabase mFirebaseDatabase;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private DatabaseReference myRef;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    mAuth = FirebaseAuth.getInstance();
    mFirebaseDatabase = FirebaseDatabase.getInstance();
    myRef = mFirebaseDatabase.getReference();
    FirebaseUser user = mAuth.getCurrentUser();
    userID = user.getUid();

    if(mAuth.getCurrentUser() == null){
        finish();
        startActivity(new Intent(this, MainActivity.class));
    }

    startSpinner();

    lvProfiles = (ListView)findViewById(R.id.lvProfiles);

    myRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // This method is called once with the initial value and again
            // whenever data at this location is updated.
            showData(dataSnapshot);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

}

private void showData(DataSnapshot dataSnapshot) {
    for(DataSnapshot ds : dataSnapshot.getChildren()){
        String x = ds.child("users").child(userID).getValue(String.class);

        ArrayList<String> array  = new ArrayList<>();
        array.add(x);
        ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,array);
        lvProfiles.setAdapter(adapter);
    }
}

My database looks like so:

{
  "users" : {

"9kV3otdvOXU0CGMZWIIxggrBrj63" : {

  "Fruit" : [ "apple", "banana", "mango" ],
  "Veg" : [ "tomato", "potato", "cabbage" ]
},
"FKazRnUjrzMuQs6dbeIIGaGju5W2" : {

  "Gluten" : [ "123", "456", "789" ]
},
"xaLZIfNudthJ8BuY6WBqYrrYPsA2" : {

  "Berries" : [ "strawberry", "raspberry", "blackberry", "blueberry", "gooseberry" ],
  "Cheese" : [ "feta", "mozzarella", "cheddar" ],
  "Kiwi" : [ "kiwi" ]
}
  }
}

Update: I changed as you suggested but "fruit" and "veg" don't appear in the spinner, could you suggest anything? here is the new code.

private void showData(DataSnapshot dataSnapshot) {

    Map<String,Object> map = dataSnapshot.child("users").child(userID).getValue(Map.class);
    ArrayList<String> array  = new ArrayList<>();
    for (Map.Entry<String,Object> entry : map.entrySet()) {

        // key contains "Fruit" or "Veg"
        String key = entry.getKey();
        // value is the corresponding list
        Object value = entry.getValue();
        array.addAll((ArrayList) value);

    }
    ArrayAdapter adapterUser = new ArrayAdapter(this,android.R.layout.simple_list_item_1,array);
    spinnerUser.setAdapter(adapterUser);

}

Rules:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "$uid === auth.uid",
        ".write": "$uid === auth.uid"
      }
    }
  }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Kyril Khaltesky
  • 85
  • 1
  • 1
  • 7
  • A separate issue, user.getUid() is called before user is checked to be null. Looks like you have a null pointer exception in your future. – Ryan Pierce Feb 12 '18 at 22:34
  • Also, point database references to the specific location at initialization, dont just point to root or "users" or else you grab everything. Don't initialize arraylists in a loop, the arraylist will be emptied and recreated every iteration. When using listview type items like spinners, do the adapter stuff in oncreate, then when you fill your "array" variable, call adapter.notifyDataSetChanged(); or else you make the system recreate the adapter object every time you call showData. – Ryan Pierce Feb 12 '18 at 23:18

1 Answers1

1

There are a number of things that are convoluted and probably aren't accomplishing what you want. I think you are looking for something that returns a map of lists per a specific user, then collects all of the list items into a spinner. If so, try this

private void showData(DataSnapshot dataSnapshot) {

   Map<String,Object> map = (Map) dataSnapshot.getValue().child("users").child(userID);
   ArrayList<String> array  = new ArrayList<>();
   for (Map.Entry<String, Object> entry : map.entrySet()) {

      // key contains "Fruit" or "Veg"
      String key = entry.getKey();
      // value is the corresponding list
      Object value = entry.getValue();
      array.addAll((ArrayList) value);

   }
   ArrayAdapter adapter = new 
       ArrayAdapter(this,android.R.layout.simple_list_item_1,array);
   lvProfiles.setAdapter(adapter);

}

I wasn't able to test this so try it, let me know what errors occur and I will edit the answer accordingly.

Ryan Pierce
  • 1,583
  • 16
  • 24
  • Hi ryan, thanks for that, I get an error here: Map map = dataSnapshot.child("users").child(userID).getValue(Map.class); ArrayList array = new ArrayList<>(); for (Map.Entry entry : map.entrySet()) { 3rd line says "incompatible types, required object, found – Kyril Khaltesky Feb 12 '18 at 23:53
  • (Map.Entry entry "incompatible types, required object, found – Kyril Khaltesky Feb 12 '18 at 23:56
  • Change "Map map = " to "Map map = ". – Ryan Pierce Feb 13 '18 at 00:09
  • Anything or just fruit and veg? – Ryan Pierce Feb 13 '18 at 00:35
  • Nothing shows up, the spinner is empty, this showed up in the log but im not sure if it relates to it "W/SyncTree: Listen at / failed: DatabaseError: Permission denied" – Kyril Khaltesky Feb 13 '18 at 00:38
  • I will post my "rules" that I have for my firebase database under updates – Kyril Khaltesky Feb 13 '18 at 00:39
  • No idea, it could be a bunch of things and distracts from the topic of the current post. – Ryan Pierce Feb 13 '18 at 00:51
  • I've never seen that issue, check out https://stackoverflow.com/questions/37688031/class-java-util-map-has-generic-type-parameters-please-use-generictypeindicator – Ryan Pierce Feb 13 '18 at 00:59
  • Ok so I set the rules to public for the time being to avoid the issue, The problem now is that it prints the Items in Veg and Fruit, basically one big list of both. instead of "Fruit" and "Veg" keys only, How could I fix that and create 2 different array maps to use them later. – Kyril Khaltesky Feb 13 '18 at 01:02
  • What would happen when the user picks fruit vs veg from the spinner? – Ryan Pierce Feb 13 '18 at 01:10
  • So the Spinner would show "fruit" and "veg" (or whatever the user has in his/her database) and when the user selects fruit it would overwrite the String [] SelectedProfile to ["apple","mango", "banana"] – Kyril Khaltesky Feb 13 '18 at 01:15
  • switch "array.addAll((ArrayList) value);" with "array.add(key);". remember that value is not an array but an arraylist when you put it into selectedProfile and that it needs to be converted. – Ryan Pierce Feb 13 '18 at 01:19
  • Thank you so much!!! Just one more question, Where exacly are the values for "Veg" stored, because I believe that the for loop overwrites them every time? – Kyril Khaltesky Feb 13 '18 at 01:31
  • make "Map map" a global variable in the class instead of local to showData() and "map.get(key);" when the user selects a key. – Ryan Pierce Feb 13 '18 at 01:38
  • 1
    Thank you I hope everything works out for you in life. – Kyril Khaltesky Feb 13 '18 at 01:40
  • Says I cant up vote because I don't have enough rep but I accepted it. – Kyril Khaltesky Feb 13 '18 at 01:57
  • Hi, sorry to bug you again, How would I convert the Object to an array of type String [] I am in a separate function trying to say map.get(key) and output all those values into an array – Kyril Khaltesky Feb 13 '18 at 22:34
  • Thanks but it says that it is an "object" and not an "arraylist" thats my problem. – Kyril Khaltesky Feb 13 '18 at 22:46
  • Ok thanks I got it, I just used the code above to cycle through all the values and used an IF to see if key == selectedItem. – Kyril Khaltesky Feb 13 '18 at 22:56