0

I want to retrieve my firebase data into a card list, but not showing anything.

public class GroupAdp extends RecyclerView.Adapter<GroupAdp.ViewHolder> {
    //Initialize activities and array list
    private Activity activity;
    ArrayList<String> arrayListGroup;

    //Create constructor
    GroupAdp(Activity activity,ArrayList<String> arrayListGroup){
        this.activity = activity;
        this.arrayListGroup = arrayListGroup;
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_row_group,parent,false);
        return new GroupAdp.ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

        //Set group name on TextView
        holder.tvName.setText(arrayListGroup.get(position));

        //Initialize member ArrayList
        ArrayList<String> arrayListMember = new ArrayList<>();

        //Using for loop to add multiple members
        for (int i=1; i<=6; i++){
            arrayListMember.add("Member " + i);
        }

        //Initialize member adapter
        MemberAdp adapterMember = new MemberAdp(arrayListMember);

        //Initialize layout manager
        LinearLayoutManager layoutManagerMember = new LinearLayoutManager(activity);

        //Set layout manager
        holder.rvMember.setLayoutManager(layoutManagerMember);

        //Set adapter
        holder.rvMember.setAdapter(adapterMember);
    }

    @Override
    public int getItemCount() {
        return arrayListGroup.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        //Initialize variable
        TextView tvName;
        RecyclerView rvMember;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            //Assign variable
            tvName = itemView.findViewById(R.id.tv_name);
            rvMember = itemView.findViewById(R.id.rv_member);
        }
    }
}
public class MemberAdp extends RecyclerView.Adapter<MemberAdp.ViewHolder> {
    //Initialize ArrayList
    ArrayList<String> arrayListMember;

    //Create constructor
    public MemberAdp(ArrayList<String> arrayListMember) {
        this.arrayListMember = arrayListMember;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //Initialize view
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_row_member,parent,false);
        return new MemberAdp.ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        //Set member name on TextView
        holder.tvName.setText(arrayListMember.get(position));
    }

    @Override
    public int getItemCount() {
        return arrayListMember.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        //Initialize variable
        TextView tvName;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            //Assign variable
            tvName = itemView.findViewById(R.id.tv_name);
        }
    }
}
public class HealthAlertActivity2 extends Fragment {

    //Initialize variable
    RecyclerView rvGroup;
    ArrayList<String> arrayListGroup;
    LinearLayoutManager layoutManagerGroup;
    GroupAdp adapterGroup;

    //@Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View healthAlertFragment = inflater.inflate(R.layout.healthalert_activity2, container, false);


        //Assign variable
        rvGroup = healthAlertFragment.findViewById(R.id.rv_group);

        //Using for loop to add multiple group
        //Used for dummy display for now
        arrayListGroup = new ArrayList<>();
//        for (int i= 1; i<=6; i++){
//            arrayListGroup.add("Group " + i);
//        }

        DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Course_ID_Section");

        reference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                Map<String, Object> map = (Map<String, Object>) snapshot.getValue();
                Log.e("LOG_TAG", "Value is:" + map);

                assert map != null;
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    Log.e("The Result", entry.getKey() + "/" + entry.getValue());

                    FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
                    String UID = user.getUid();

                    if (UID.equals(entry.getValue())) {
                        arrayListGroup.add("Class" + entry.getValue());
                    }

                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
                Log.e("LOG_TAG", "Failed to read value.", error.toException());
            }
        });


        //Initialize group adapter
        adapterGroup = new GroupAdp(getActivity(),arrayListGroup);

        //Initialize layout manager
        layoutManagerGroup = new LinearLayoutManager(getActivity());

        //Set layout manager
        rvGroup.setLayoutManager(layoutManagerGroup);

        //Set adapter
        rvGroup.setAdapter(adapterGroup);
        return healthAlertFragment;
    }
}

enter image description here

I want the Group name to be the Course_ID_Section, for example, CSCI-110-MO1. Only if the value inside of this key(CSCI-110-MO1) is the same as the firebase UID. Otherwise, perform no action.

Currently, I am dealing with this kind output:

E/LOG_TAG: Value is:{CSCI-110-M01={BiazGfcXiBYKUUGk4NGwXjJ5C7k2=***********, nGrAfIS6NgbBlkmSPUA0zm4qwQb2=***********}, CSCI-415-M01={BiazGfcXiBYKUUGk4NGwXjJ5C7k2=***********, nGrAfIS6NgbBlkmSPUA0zm4qwQb2=***********}, CSCI-455-M03={BiazGfcXiBYKUUGk4NGwXjJ5C7k2=***********, nGrAfIS6NgbBlkmSPUA0zm4qwQb2=***********}, CSCI-300-M02={BiazGfcXiBYKUUGk4NGwXjJ5C7k2=***********, nGrAfIS6NgbBlkmSPUA0zm4qwQb2=***********}, CSCI-318-M01={BiazGfcXiBYKUUGk4NGwXjJ5C7k2=***********, nGrAfIS6NgbBlkmSPUA0zm4qwQb2=***********}}
E/The Result: CSCI-110-M01/{BiazGfcXiBYKUUGk4NGwXjJ5C7k2=***********, nGrAfIS6NgbBlkmSPUA0zm4qwQb2=***********}
E/The Result: CSCI-415-M01/{BiazGfcXiBYKUUGk4NGwXjJ5C7k2=***********, nGrAfIS6NgbBlkmSPUA0zm4qwQb2=***********}
    CSCI-455-M03/{BiazGfcXiBYKUUGk4NGwXjJ5C7k2=***********, nGrAfIS6NgbBlkmSPUA0zm4qwQb2=***********}
    CSCI-300-M02/{BiazGfcXiBYKUUGk4NGwXjJ5C7k2=***********, nGrAfIS6NgbBlkmSPUA0zm4qwQb2=***********}
    CSCI-318-M01/{BiazGfcXiBYKUUGk4NGwXjJ5C7k2=***********, nGrAfIS6NgbBlkmSPUA0zm4qwQb2=***********}

Not sure if it is the "=" causing me the problem. Only want to compare firebase UID in this case.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

1 Answers1

1

You're loading data from:

DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Course_ID_Section");

This means the snapshot you get has two nested, levels of dynamic nodes under it: the CSCI-110-M01 level, and then the level with the UIDs. So in your onDataChange you'll need two nested loops to iterate over both levels.

I'd also recommend iterating over the getChildren() of the snapshot, and only getting the values out of the snapshot at the lowest level.

Combined, that becomes:

reference.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
        String UID = user.getUid();

        for (DataSnapshot courseSnapshot: snapshot.getChildren()) {            
            for (DataSnapshot userSnapshot: courseSnapshot.getChildren()) {            
                if (UID.equals(userSnapshot.getKey())) {
                    arrayListGroup.add("Class" + userSnapshot.getValue(String.class));
                }
            }
        }
    }
    ...
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • I tried your code. However, my card list displays nothing, just a blank. I tested it when I initialize it with a for loop, it worked. Not sure what happen. – Wentao Yang May 04 '21 at 21:56
  • If you step through the updated code in a debugger, does it step into each of the for loops? If so, what values do you see for `userSnapshot.getKey()` and `userSnapshot.getValue(String.class)`? – Frank van Puffelen May 04 '21 at 22:00
  • I check the result in my debugger, I got ```E/LOG_TAG: BiazGfcXiBYKUUGk4NGwXjJ5C7k2``` for getKey(), person's name for getValue(String.class). In my case, I want to see if UID matches, if it does, return the CSCI-110-MO1 for example. So, do I add courseSnapshot instead? Haven't tried it, are we allowed to do it in this way? – Wentao Yang May 04 '21 at 22:08
  • Do get one message in my logcat ```I/Choreographer: Skipped 32 frames! The application may be doing too much work on its main thread.``` Is this the reason why it displays nothing? – Wentao Yang May 04 '21 at 22:29
  • That message is about rendering speed, and typically pretty harmless unless you get it all the time. If you want to show the course nbame, that'd be `courseSnapshot.getKey()` indeed. I also recommend actually storing the "courses per user" in a separate node, instead of the query you do now, as it scales much better. See my answer here for an example: https://stackoverflow.com/questions/40656589/firebase-query-if-child-of-child-contains-a-value – Frank van Puffelen May 04 '21 at 22:39
  • Not very sure if I understand you correctly. Do you mean that I should have list like ```FirebaseUID{Courses}``` instead of ```Course{FirebaseUID : names}```? – Wentao Yang May 04 '21 at 22:55
  • I run Log.e on my code. Every first time I try to execute or display it. It give me such message ```V/FA: Inactivity, disconnecting from the service``` – Wentao Yang May 05 '21 at 00:08
  • Did you try `courseSnapshot.getKey()` yet? Is that the value you want? – Frank van Puffelen May 05 '21 at 01:15
  • I tried that as well. Same issue, nothing will display, only a blank sheet. I am pretty sure that the code you post can retrieve info from firebase. Maybe there is something going on with my nested recycler view design. – Wentao Yang May 05 '21 at 15:47
  • Yeah that could be. This is why we ask for a **minimal** reproduction, as you definitely had problems in the database code (which my answer addresses), but there may be more problems. So my answer may have helped you fix the first problem, but not the second. I highly recommend reading [how to create a minimal, complete, verifiable example](http://stackoverflow.com/help/mcve) to prevent getting into a situation like this. – Frank van Puffelen May 05 '21 at 16:40
  • I give it one more try. But this time, I did both ```getKey()``` and ```getValue()``` on courseSnapshot. I got an error ```com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.HashMap to String``` for getValue(String.value). Maybe that's the reason why, so my getItemcount return null? Not quite sure. Maybe I still need to use Map for my case? – Wentao Yang May 05 '21 at 18:13
  • The value of `courseSnapshot` is a `Map` and not a string. The value of `userSnapshot` is a string, which is why this works: `userSnapshot.getValue(String.class)` – Frank van Puffelen May 05 '21 at 18:27
  • If I want to get only one value (Firebase UID) from courseSnapshot. What should I do? I tried to implement a map on it, but it returns every value inside courseSnapshot. Like this ```BiazGfcXiBYKUUGk4NGwXjJ5C7k2=***********``` – Wentao Yang May 05 '21 at 19:30
  • A course has multiple child nodes, one for each UID. That's precisely why you need a second loop, as shown in my answer. – Frank van Puffelen May 05 '21 at 22:46
  • I got it working. I forgot to notifyDataSetChange() – Wentao Yang May 06 '21 at 15:22