1

I have created a nested RecyclerView. I fetch data from firebase, then I insert it into one RecyclerView which uses another RecyclerView. In my fragment the code is:


    private Map<Character,List<QueryDocumentSnapshot>> carsDocuments;
    private DocumentReference connectedGroupDocumentRef;

    private RecyclerView carsRecyclerViewCards;
    private CarDetailsCardAdapter cardsAdapter;

    private View fragmentView;

    public CarsDetailsFragment() {}

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        fragmentView = inflater.inflate(R.layout.fragment_cars_details, container, false);

        // On add new car click
        FloatingActionButton addNewCarFab = (FloatingActionButton) fragmentView.findViewById(R.id.fab_add_new_car);
        addNewCarFab.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getActivity(), AddNewCar.class);
                fragmentView.getContext().startActivity(intent);
            }
        });

        carsDocuments = new HashMap<>();
        carsRecyclerViewCards = (RecyclerView) fragmentView.findViewById(R.id.rv_car_details_cards);
        connectedGroupDocumentRef = getConnectedGroupReference();
        connectedGroupDocumentRef.collection("cars").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {

            @Override
            public void onComplete(@NonNull Task<QuerySnapshot> task) {
                if (task.isSuccessful()) {
                    RelativeLayout emptyView = fragmentView.findViewById(R.id.cars_details_empty_view);
                    if (task.getResult() == null || task.getResult().isEmpty()) {
                        emptyView.setVisibility(View.VISIBLE);
                        carsRecyclerViewCards.setVisibility(View.GONE);
                    } else {
                        for (QueryDocumentSnapshot document : task.getResult()) {
                            char letter = getFirstLetter(document.getString("type"));
                            List<QueryDocumentSnapshot> carsList = carsDocuments.get(letter);
                            if (carsList == null) {
                                carsList = new ArrayList<>();
                                carsList.add(document);
                                carsDocuments.put(letter, carsList);
                            } else {
                                carsList.add(document);
                            }
                        }
                        emptyView.setVisibility(View.GONE);
                        carsRecyclerViewCards.setVisibility(View.VISIBLE);
                        cardsAdapter = new CarsCardAdapter(getActivity(), carsDocuments);
                        carsRecyclerViewCards.setLayoutManager(new LinearLayoutManager(getActivity()));
                        carsRecyclerViewCards.setAdapter(cardsAdapter);
                        setRecyclerViewListener();
                    }
                }
            }
        });
    }


    private void setRecyclerViewListener() {
          connectedGroupDocumentRef.collection("cars").addSnapshotListener(new EventListener<QuerySnapshot>() {

            @Override
            public void onEvent(@Nullable QuerySnapshot value,
                                @Nullable FirebaseFirestoreException e) {
                if (e != null) {
                    Log.d(this.getClass().getName(), "addSnapshotListener:failure", e);
                    return;
                }

                carsDocuments.clear();
                for (QueryDocumentSnapshot document : value) {
                    char letter = getFirstLetter(document.getString("full_name"));
                    List<QueryDocumentSnapshot> carsList = carsDocuments.get(letter);
                    if (carsList == null) {
                        carsList = new ArrayList<>();
                        carsList.add(document);
                        carsDocuments.put(letter, carsList);
                    } else {
                        carsList.add(document);
                    }
                }
                System.out.println("I'm HERE");
                cardsAdapter.notifyDataSetChanged();
                //carsRecyclerViewCards.invalidate(); 
            }
        });
    }

In the CarsCardAdapter class:

public class CarsCardAdapter extends RecyclerView.Adapter<CarsCardAdapter.ViewHolder> {
    private Map<Character, List<QueryDocumentSnapshot>> carsDocuments;
    private Character[] carsLetters;
    private Activity activity;

    private UsersAdapter adapterMember;

    public class ViewHolder extends androidx.recyclerview.widget.RecyclerView.ViewHolder {
        private TextView textLetter;
        private RecyclerView recyclerViewUsers;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            textLetter = itemView.findViewById(R.id.cars_details_letter);
            recyclerViewUsers = itemView.findViewById(R.id.car_details_users);
        }
    }

    CarsCardAdapter(Activity activity, Map<Character,List<QueryDocumentSnapshot>> carsDocuments) {
        this.activity = activity;
        if (carsDocuments != null) {
            this.carsDocuments = carsDocuments;
            this.carsLetters = carsDocuments.keySet().toArray(new Character[0]);
        }
    }

    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_car_cards, parent, false));
    }

    public void onBindViewHolder(ViewHolder holder, int position) {
        final char letter = this.carsLetters[position];
        final List<QueryDocumentSnapshot> carsList = carsDocuments.get(letter);
        holder.textLetter.setText(String.valueOf(letter));
        adapterMember = new UsersAdapter(activity,carsList);
        holder.recyclerViewUsers.setLayoutManager(new LinearLayoutManager(this.activity));
        holder.recyclerViewUsers.setAdapter(this.adapterMember);
    }

    public int getItemCount() {
        return this.carsLetters.length;
    }
}

And the important method is setRecyclerViewListener which updates the RecyclerView once the database collection is changed. As you can see I remove the carsDocuments and insert all of the reports. Then I update the adapter by calling notifyDataSetChanged. Also tried invalidate. I know for sure that I get into the listener because I'm HERE is printed to the log. Also note that documentRef.collection("cars").get()... is being executed in the onCreateView of the my fragment. the What could be the issue?

abuka123
  • 364
  • 1
  • 9
  • add carsList to your adapter before calling notifyDataSetChanged(); – Jason Jun 10 '20 at 16:26
  • @Jason Hi, why? In this topic: [Link](https://stackoverflow.com/questions/31367599/how-to-update-recyclerview-adapter-dat) they say that I need to just use `clear` and then `notifyDataSetChanged`. – abuka123 Jun 10 '20 at 16:39
  • Can you post the full codes? Activity and adapter – Jason Jun 10 '20 at 18:01
  • @Jason I have added the fragment. Do you also need the inner adapter `UsersAdapter`? – abuka123 Jun 10 '20 at 18:15

1 Answers1

1

First of all, add this:

carsRecyclerViewCards.setVisibility(View.VISIBLE);
                    cardsAdapter = new CarsCardAdapter(getActivity(), carsDocuments);
                    carsRecyclerViewCards.setLayoutManager(new LinearLayoutManager(getActivity()));
                    carsRecyclerViewCards.setAdapter(cardsAdapter);

Inside your setRecyclerViewListener(); like u did in the addOnSuccessListener

Then delete this:

   connectedGroupDocumentRef.collection("cars").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {

        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {
                RelativeLayout emptyView = fragmentView.findViewById(R.id.cars_details_empty_view);
                if (task.getResult() == null || task.getResult().isEmpty()) {
                    emptyView.setVisibility(View.VISIBLE);
                    carsRecyclerViewCards.setVisibility(View.GONE);
                } else {
                    for (QueryDocumentSnapshot document : task.getResult()) {
                        char letter = getFirstLetter(document.getString("type"));
                        List<QueryDocumentSnapshot> carsList = carsDocuments.get(letter);
                        if (carsList == null) {
                            carsList = new ArrayList<>();
                            carsList.add(document);
                            carsDocuments.put(letter, carsList);
                        } else {
                            carsList.add(document);
                        }
                    }
                    emptyView.setVisibility(View.GONE);
                    carsRecyclerViewCards.setVisibility(View.VISIBLE);
                    cardsAdapter = new CarsCardAdapter(getActivity(), carsDocuments);
                    carsRecyclerViewCards.setLayoutManager(new LinearLayoutManager(getActivity()));
                    carsRecyclerViewCards.setAdapter(cardsAdapter);
                    setRecyclerViewListener();
                }
            }
        }
    });

And put this

 setRecyclerViewListener();

In its place in onCreate

Jason
  • 334
  • 3
  • 6
  • You are the best! One question if you may - if I remove some user, the order of the letters is not alphabetically. Do you know maybe why and how to fix it? – abuka123 Jun 10 '20 at 18:50
  • 1
    No I don't know why, maybe you should post another question about that. If this answer worked, pls mark it as accepted for future reference – Jason Jun 10 '20 at 19:06