data from firebase realtime database is loading slowly in recyclerview

Issue

I am trying to fetch data from firbase and show it in recyclerview. It takes about 30-50 seconds for recyclerview to load the data. There is only one node and still the data takes too much time. Below is the code of my adapter class.

public class SellerProductsAdapter extends RecyclerView.Adapter<SellerProductsAdapter.ProductsViewHolder> {

    ArrayList<HomeFragmentModel> data = new ArrayList<>();
    Context context;
    String productNameO;

    public SellerProductsAdapter(ArrayList<HomeFragmentModel> data, Context context) {
        this.data = data;
        this.context = context;
    }

    @NonNull
    @Override
    public ProductsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.home_fragment_products_single_row, parent, false);
        return new ProductsViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ProductsViewHolder holder, int position) {
        Picasso.get()
                .load(String.valueOf(data.get(position).getImage1()))
                .into(holder.productImage);
        holder.productName.setText(String.valueOf(data.get(position).getName()));
        holder.productPrice.setText(String.valueOf("Rs. " + data.get(position).getPrice()));
        Log.d("TAG", "Data Product Name is: " + data.get(position).getName());

    }

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

Viewholder class:

public class ProductsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, PopupMenu.OnMenuItemClickListener {
    ShapeableImageView productImage;
    TextView productName, productPrice;
    ConstraintLayout dots;

    public ProductsViewHolder(@NonNull View itemView) {
        super(itemView);
        productImage = itemView.findViewById(R.id.homeProductImage);
        productName = itemView.findViewById(R.id.homeProductName);
        productPrice = itemView.findViewById(R.id.homeProductPrice);
        dots = itemView.findViewById(R.id.dotsLayout);

        dots.setOnClickListener(this);
    }

I have tried to log the fetched the exact data in my fragment and it takes only 1-2 seconds. below is the HomeFragment code

databaseReference = FirebaseDatabase.getInstance().getReference();
user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null){
    UID = user.getUid();
}

data = new ArrayList<>();

databaseReference.child("Product").child(UID).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        for (DataSnapshot dataSnapshot : snapshot.getChildren()){
            for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()){
                HomeFragmentModel homeFragmentModel = dataSnapshot1.getValue(HomeFragmentModel.class);
                data.add(homeFragmentModel);
                String key = dataSnapshot1.getKey();
                Log.d("TAG", "Data Key is: " + dataSnapshot1.child("name").getValue());
            }
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {

    }
});
recyclerView.setItemViewCacheSize(10);
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
adapter = new SellerProductsAdapter(data, getContext());
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();

Snapshot of my db structure
enter image description here

Nevia node data:

enter image description here

Solution

The call to notifyDataSetChanged needs to be inside onDataChange, so that it tells the adapter to refresh its views whenever the data is loaded.

databaseReference.child("Product").child(UID).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        for (DataSnapshot dataSnapshot : snapshot.getChildren()){
            for (DataSnapshot dataSnapshot1 : dataSnapshot.getChildren()){
                HomeFragmentModel homeFragmentModel = dataSnapshot1.getValue(HomeFragmentModel.class);
                data.add(homeFragmentModel);
                String key = dataSnapshot1.getKey();
                Log.d("TAG", "Data Key is: " + dataSnapshot1.child("name").getValue());
            }
            adapter.notifyDataSetChanged(); // 👈
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {
        throw error.toException(); // 👈 never ignore errors
    }
});
recyclerView.setItemViewCacheSize(10);
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 2));
adapter = new SellerProductsAdapter(data, getContext());
recyclerView.setAdapter(adapter);

Answered By – Frank van Puffelen

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published