Firebase UI: Solution to receive all keys from a child and use it to receive information from another node and fill it in a Recyclerview?

Viewed 299

I am searching for a solution to get the data from my child "medication" and use the IDs to receive specific data from the "medication_plan" node and displaying them in a Recyclerview.

DB-Structure:

At the moment I am using Firebase UI to fill my Recyclerview

private DatabaseReference mRef;

private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private FirebaseRecyclerAdapter<Medication,MedicationViewHolder> mAdapter;

List<User> items = new ArrayList<>();

User user = new User();

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

    mRecyclerView = findViewById(R.id.my_recycler_view);
    mRecyclerView.setHasFixedSize(true);

    mLayoutManager = new LinearLayoutManager(this);
    mRecyclerView.setLayoutManager(mLayoutManager);

    setData();
}

private void setData() {
    Query query = FirebaseDatabase.getInstance().getReference().child("Medication_plan");
    FirebaseRecyclerOptions<Medication> options = new FirebaseRecyclerOptions.Builder<Medication>()
            .setQuery(query,Medication.class)
            .build();

    mAdapter = new FirebaseRecyclerAdapter<Medication, MedicationViewHolder>(options) {
        @Override
        protected void onBindViewHolder(@NonNull MedicationViewHolder holder, int position, @NonNull Medication model) {
            final Medication tempmed = new Medication(model.getDr()
                    ,model.getMedicine()
                    ,model.getDate()
                    ,model.getComment());

            holder.mDoctor.setText(model.getDr());
            holder.mMedicine.setText(model.getMedicine());
            holder.mDate.setText(model.getDate());
        }

        @NonNull
        @Override
        public MedicationViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
            View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.my_text_view,viewGroup,false);
            MedicationViewHolder vh = new MedicationViewHolder(v);
            return vh;
        }
    };

    mRecyclerView.setAdapter(mAdapter);
}

@Override
protected void onStart() {
    mAdapter.startListening();
    super.onStart();
}

@Override
protected void onStop() {
    mAdapter.stopListening();
    super.onStop();
}

When I use this code I get every medication plan, but I only want the specific plans from the user.

2 Answers

Add this function to get your data:

ArrayList<String> list = new ArrayList<String>();
DatabaseReference ref= FirebaseDatabase.getInstance().getReference("User").child("R3").child("medication");
ref.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot snap: dataSnapshot.getChildren()) {
            list.add(snap.child("id").getValue(String.class));
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.w(TAG, "onCancelled", databaseError.toException());
    }
});

After that add this code to get the second data info:

ArrayList<String> listOfSomething = new ArrayList<String>();
DatabaseReference ref=  FirebaseDatabase.getInstance().getReference("Medication_plan");
ref.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for (String s: list) {
            listOfSomething.add(dataSnapshot.child("s").child("comment").getValue(String.class));
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.w(TAG, "onCancelled", databaseError.toException());
    }
});

in my example I retrieve the comments. You can change it in whatever you want to retrieve.

To get only the medicine that corresponde to a specific user, you need to query your database twice. Once to get the medicine ids and second to get the details of your medicines like in the following lines of code:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference medicationRef = rootRef.child("User").child("r3").child("medication");
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String medicationKey = ds.getKey();

            DatabaseReference medicationKeyRef = rootRef.child("Medication_plan").child(medicationKey);
            ValueEventListener eventListener = new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    for(DataSnapshot ds : dataSnapshot.getChildren()) {
                        Medication medication = ds.getValue(Medication.class);
                        Log.d(TAG, medication.getMedicine());
                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {
                    Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
                }
            };
            medicationKeyRef.addListenerForSingleValueEvent(eventListener);
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
    }
};
medicationRef.addListenerForSingleValueEvent(valueEventListener);

The output in the logcat will be:

Aspirin
Paracetamol

Beside that, you'll also should simplify the User node like in following schema:

Firebase-root
   |
   --- User
        |
        --- R3
            |
            --- lastname: "Hirsch"
            |
            --- medication
            |      |
            |      --- 1234: true
            |      |
            |      --- assf12: true
            |
            --- name: "Rob"

The above code will also work for this structure.

Related