Search code examples
javaandroidandroid-fragmentsandroid-recyclerviewandroid-viewpager

Prevent repeating of items when i back to fragment


In my application , I have ViewPager containing 3 fragments (Home , Profile and More)

Home Fragment contain RecyclerView when i navigate from Home Fragment to Profile Fragment or More Fragment, it work like expected.

But when i navigate back to Home Fragment , items in RecyclerView duplicate...

And when i navigate again and back , it duplicate again

Here is my MainActivity.java Code:

public class MainActivity extends AppCompatActivity {

 TabLayout mainTabLayout;
 ViewPager mainViewPager;

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



        mainTabLayout = findViewById(R.id.main_tablayout);
        mainViewPager = findViewById(R.id.main_viewpager);
        mainTabLayout.setupWithViewPager(mainViewPager);

        //to put mainTabLayout Icons...
        MainTabLayoutIcons();

    }

 //to Change MainLayout Icons...
    private void MainTabLayoutIcons() {

        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());

        // add fragments to the adapter
        adapter.addFragment(new Home());
        adapter.addFragment(new MyActivity());
        adapter.addFragment(new More());

        mainViewPager.setOffscreenPageLimit(0);
        mainViewPager.setAdapter(adapter);


        // Select Home tab as default tab on startup
        mainViewPager.setCurrentItem(0);
        mainTabLayout.getTabAt(0).select();

        // Set tabs Initial icons
        mainTabLayout.getTabAt(0).setIcon(R.drawable.home_black);
        mainTabLayout.getTabAt(1).setIcon(R.drawable.user_outline);
        mainTabLayout.getTabAt(2).setIcon(R.drawable.more_outline);

        /* tabSelectedListener to change the icon color once it is selected
        // and change it back once another tab is selected */
        mainTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {

                if (tab.getPosition() == 0) {
                    mainTabLayout.getTabAt(0).setIcon(R.drawable.home_black);
                    mainTabLayout.getTabAt(1).setIcon(R.drawable.user_outline);
                    mainTabLayout.getTabAt(2).setIcon(R.drawable.more_outline);

                }
                if (tab.getPosition() == 1) {
                    mainTabLayout.getTabAt(0).setIcon(R.drawable.home_outline);
                    mainTabLayout.getTabAt(1).setIcon(R.drawable.user_);
                    mainTabLayout.getTabAt(2).setIcon(R.drawable.more_outline);
                }

                if (tab.getPosition() == 2) {
                    mainTabLayout.getTabAt(0).setIcon(R.drawable.home_outline);
                    mainTabLayout.getTabAt(1).setIcon(R.drawable.user_outline);
                    mainTabLayout.getTabAt(2).setIcon(R.drawable.more_black);
                }
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                //no need for it
            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {
               //no need for it

           }

        });
    }


}

and here is ViewPagerAdapter Code:

  //Adapter for mainActivity ...
    public class ViewPagerAdapter extends FragmentStatePagerAdapter {

        private final List<Fragment> fragmentList = new ArrayList<>();

        public ViewPagerAdapter(@NonNull FragmentManager fm) {
            super(fm);
        }
        
        @Override
        public Fragment getItem(int position) {
            
            return fragmentList.get(position);
        }

        @Override
        public int getCount() {
            return fragmentList.size();
        }


        public void addFragment(Fragment fragment) {
            fragmentList.add(fragment);
        }

    }

and here is first Fragment Home.java Code:


public class Home extends Fragment {

    View v;

    public SwipeRefreshLayout mSwipeRefreshLayout;

    public RecyclerView mainRecyclerView;

    private LinearLayoutManager linearLayoutManager;

    public final List<MyActivityModel> mainPosts = new ArrayList<>();
    private PostAdapter mAdapter;


    public Home() {
        /*Required Empty Constructor... */
    }


    @Override
    public View onCreateView(LayoutInflater layoutInflater, ViewGroup container, Bundle bundle) {

        v = layoutInflater.inflate(R.layout.fragment_home, container, false);

        mSwipeRefreshLayout = (SwipeRefreshLayout) v.findViewById(R.id.mainSwipeRefresh);

     
        mainRecyclerView = (RecyclerView) v.findViewById(R.id.MainRecyclerView);

        linearLayoutManager = new LinearLayoutManager(getActivity());

        mainRecyclerView.setLayoutFrozen(true);

mainRecyclerView.setNestedScrollingEnabled(false);

        mainRecyclerView.setLayoutManager(linearLayoutManager);

        mAdapter = new PostAdapter(mainPosts);

mainRecyclerView.setAdapter(mAdapter);

        Swipe();
        LoadPosts();
          
        return v;
    }


    /**
     * -----------------TODO: to load posts in Home RecyclerView...----------------
     */
    public void LoadPosts() {

        Query database = FirebaseDatabase.getInstance().getReference().child("Posts");
        database.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {

                if (snapshot.exists()) {

                    MyActivityModel post = snapshot.getValue(MyActivityModel.class);

                    mainPosts.add(0, post); 
                    mAdapter.notifyDataSetChanged();
                }


            }

            @Override
            public void onChildChanged(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot snapshot) {
            }

            @Override
            public void onChildMoved(@NonNull DataSnapshot snapshot, @Nullable String previousChildName) {
            }

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

        });
 

   

    }

     
  private void Swipe() {

        //to refresh page after swipe
        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {

                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {

                        try {

                            mainPosts.clear();
                          
                            LoadPosts();

                          mSwipeRefreshLayout.setRefreshing(false);

                            Toast.makeText(v.getContext(),"Refreshed", Toast.LENGTH_SHORT).show();

                        } catch (Exception e) {

                            mSwipeRefreshLayout.setRefreshing(false);

                        }

                    }
                }, 500);
            }

        });


    }
}

and this is an image showing item reeating

Anyone can help me how to prevent this duplication...


Solution

  • You may need to use FragmentPagerAdapter instead of FragmentStatePagerAdapter. Also, set mainRecyclerView.setLayoutFrozen(true); to false because, it will stop everything in recyclerView.

    When you need to use FragmentPagerAdapter?

    FragmentStatePagerAdapter is more useful when there are a large number of pages, working more like a list view. When pages are not visible to the user, their entire fragment may be destroyed, only keeping the saved state of that fragment. This allows the pager to hold on to much less memory associated with each visited page as compared to FragmentPagerAdapter at the cost of potentially more overhead when switching between pages.

    Example of FragmentPagerAdapter:

        class viewpager_class extends FragmentPagerAdapter {
        int tabcount;
    
        public viewpager_class(@NonNull FragmentManager fm, int tab_count) {
            super(fm, tab_count);
            this.tabcount = tab_count;
        }
    
        @NonNull
        @Override
        public Fragment getItem(int position) {
            switch (position) {
                case 0:
                    Fragment1 fragment1 = new Fragment1 ();
                    return todayBAFragment;
                case 1:
                    Fragment2 fragment2 = new Fragment2 ();
                    return todayReminderDue;
                case 2:
                    Fragment3 fragment3 = new Fragment3 ();
                    return currentTransaction;
                default:
                    return null;
            }
        }
    
        @Override
        public int getCount() {
            return tabcount;
        }
    }
    

    Also, set adapter into ViewPager wherever you want show viewPager:

        //set adapter into viewpager
        viewpager_class viewpagerClass = new viewpager_class(getChildFragmentManager(), tabLayout.getTabCount());
        viewPager.setAdapter(viewpagerClass);
        viewPager.setOffscreenPageLimit(2);
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));