Home > OS >  How to prevent duplicate items in pagination - Firebase Realtime Database?
How to prevent duplicate items in pagination - Firebase Realtime Database?

Time:09-08

After scrolling to bottom of the RecyclerView, Data is fetched again from the Start which ultimately ends in infinite scrolling and never ends. I am using Firebase Realtime Database

This is my code :

String last_key = "", last_node = "";
boolean isMaxData = false, isScrolling = false;
int ITEM_LOAD_COUNT = 10;
int currentitems, tottalitems, scrolledoutitems;
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
                isScrolling = true;

            }

        }
        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            currentitems = manager.getChildCount();
            tottalitems = manager.getItemCount();
            scrolledoutitems = manager.findFirstVisibleItemPosition();

            if (isScrolling && currentitems   scrolledoutitems == tottalitems) {
                //  Toast.makeText(getContext(), "fetch data", Toast.LENGTH_SHORT).show();
                isScrolling = false;
                //fetch data
                progressbar.setVisibility(View.VISIBLE);
                Log.e("On","Scrolled, Reached Bottom");
                getUsers();

            }

        }
    });

This is how I am getting items from database :

 private void getUsers() {
        if (!isMaxData) // 1st fasle
        {
            Query query;

            if (TextUtils.isEmpty(last_node))
                query = FirebaseDatabase.getInstance().getReference("ShopCategories").child(recPosition).child("items")
                        .orderByKey()
                        .limitToFirst(ITEM_LOAD_COUNT);
            else
                query = FirebaseDatabase.getInstance().getReference("ShopCategories").child(recPosition).child("items")
                        .orderByKey()
                        .startAt(last_node)
                        .limitToFirst(ITEM_LOAD_COUNT);

            query.addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot snapshot) {
                    if (snapshot.hasChildren()) {
                        List<TrendingModel> newUsers = new ArrayList<>();
                        for (DataSnapshot userSnapshot : snapshot.getChildren()) {
                            newUsers.add(userSnapshot.getValue(TrendingModel.class));
                            Log.e("NewUsersList","" userSnapshot.child("title").getValue(String.class));
                        }
//                        Log.e("NewUsersList","" newUsers);

                        last_node = newUsers.get(newUsers.size() - 1).getId();    //10  if it greater than the toatal items set to visible then fetch data from server

                        if (!last_node.equals(last_key))
                            newUsers.remove(newUsers.size() - 1);    // 19,19 so to renove duplicate removeone value
                        else
                            last_node = "end";

                        // Toast.makeText(getContext(), "last_node" last_node, Toast.LENGTH_SHORT).show();

                        trendingAdapter.addAll(newUsers);
                        trendingAdapter.notifyDataSetChanged();


                    } else   //reach to end no further child avaialable to show
                    {
                        isMaxData = true;
                    }

                    progressbar.setVisibility(View.GONE);

                }

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

                }
            });

        } else {
            progressbar.setVisibility(View.GONE); //if data end
        }
    }

This is my code to get the Last Key from FirebaseRealtime Database :

  private void getLastKeyFromFirebase() {
    Query getLastKey = FirebaseDatabase.getInstance().getReference("ShopCategories").child(recPosition).child("items")
            .orderByKey()
            .limitToLast(1);

    getLastKey.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) {
            for (DataSnapshot lastkey : snapshot.getChildren())
                last_key = lastkey.getKey();
            //   Toast.makeText(getContext(), "last_key" last_key, Toast.LENGTH_SHORT).show();
            Log.e("LastKey","" last_key);

        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            Toast.makeText(CategoryDetailActivity.this, "can not get last key", Toast.LENGTH_SHORT).show();
        }
    });


}

This is the part of the Adapter class code : (not putting entire code, as it might get messy)

 List<TrendingModel> trendingModelList;
Context context;

public TrendingAdapter(Context context) {
    this.trendingModelList = new ArrayList<>();
    Log.e("New","Instance creating");
    this.context = context;
}

public void addAll(List<TrendingModel> newUsers) {
    int initsize = trendingModelList.size();
    trendingModelList.addAll(newUsers);
    notifyItemRangeChanged(initsize, newUsers.size());
}

and the model class : (not putting entire code, as it might get messy):

 public String getId() {
    return id;
}

CodePudding user response:

You can either skip the duplicate item you get in your application code, or you can use the startAfter operation instead of startAt here:

query = FirebaseDatabase.getInstance().getReference("ShopCategories").child(recPosition).child("items")
        .orderByKey()
        .startAfter(last_node) //            
  • Related