Updating the contents on tab changed in view pager

anand picture anand · May 21, 2015 · Viewed 8.4k times · Source

I am scracthing my head for past 1 day but unable to find the solution. In mine application there are two tabs under the toolbar

  • First tab is USER-TAB
  • the second one is ADMIN-TAB

In both the tabs there are the listView. When a ListItem on the USER-TAB is clicked a dialog appears and user take some action.

Now after this when the ADMIN-TAB is Selected the Admin should get refreshed with new sets of data. But It's not. On selecting the ADMIN-TAB the onResume() method and everyting is getting called but it is not able to update the list.

I wont be able to write the Whole code, I am giving some snippet. Basically I have taken the code from this link
https://github.com/codepath/android_guides/wiki/Sliding-Tabs-with-PagerSlidingTabStrip

In My Main Activity I have written the OpPageChangeListener.

public class MaterialTab extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.material_main_sample);
        // Get the ViewPager and set it's PagerAdapter so that it can display items
        ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
        viewPager.setAdapter(new SampleFragmentPagerAdapter(getSupportFragmentManager()));
        // Give the PagerSlidingTabStrip the ViewPager
        PagerSlidingTabStrip tabsStrip = (PagerSlidingTabStrip) findViewById(R.id.tabs);
        // Attach the view pager to the tab strip
        tabsStrip.setViewPager(viewPager);
        tabsStrip.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }
            @Override
            public void onPageSelected(int position) {
                if(position == 0){
                    MileUserFragment userFragment = new MileUserFragment();
                    final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                    ft.detach(userFragment);
                    ft.attach(userFragment);
                    ft.commit();
                } if(position == 1){
                    MileAdminFragment adminFragment = new MileAdminFragment();
                    final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                    ft.detach(adminFragment);
                    ft.attach(adminFragment);
                    ft.commit();
                }
            }
            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });
    }
}

OnPageSelected You can see I am detaching and reattaching the fragment.Everything is working fine. Both Fragments OnResume() are getting called but the List is not getting changed. I don't undrstand why

For additional assistance i am adding snippet one Fragment. Hope this will give some Idea where i might be going wrong

public class MileUserFragment extends Fragment {
@Override
    public void onResume() {
        super.onResume();
        new GetAdminDbTask().execute();

        if(!internetUtil.isConnectedToInternet(getActivity())){
            mSwipeRefreshLayout.setRefreshing(false);
            mSwipeRefreshLayout.setEnabled(false);
        }
    }

 public class GetAdminDbTask extends AsyncTask<Admin, Void, String> {
        @Override
        protected String doInBackground(Admin... parmas) {
            _adminList = shipmentDbHandler.getAllAdmin();
            return "";
        }
        @Override
        protected void onPostExecute(String str) {
            mAdminAdapter = new AdminAdapter(getActivity(), _adminList);
            adminListView.setAdapter(mAdminAdapter);
            mAdminAdapter.notifyDataSetChanged();
            // Set the refresh Listener to false after the list has been loaded with new set of data
            if (mSwipeRefreshLayout.isRefreshing()) {
                mSwipeRefreshLayout.setRefreshing(false);
            }

            if(_adminList.size() > 0 ){
                mAdminAdapter = new AdminAdapter(getActivity(), _adminList);
                adminListView.setAdapter(mAdminAdapter);
                mAdminAdapter.notifyDataSetChanged();
            }
        }
    }
}

public class SampleFragmentPagerAdapter extends FragmentPagerAdapter {
    final int PAGE_COUNT = 2;
    private String tabTitles[] = new String[] { "Tab1", "Tab2" };
    private FragmentManager fragmentManager;

    public SampleFragmentPagerAdapter(FragmentManager fm) {
        super(fm);
        this.fragmentManager = fm;
    }

    @Override
    public int getCount() {
        return PAGE_COUNT;
    }

    @Override
    public Fragment getItem(int position) {
        FragmentTransaction ft = null;
        if(position == 0){
            MileUserFragment userFragment = new MileUserFragment();
            return userFragment;

        }
        if(position == 1){
            MileAdminFragment adminFragment = new MileAdminFragment();
            return archiveFragment;
        }

    }

    @Override
    public CharSequence getPageTitle(int position) {
        // Generate title based on item position
        return tabTitles[position];
    }
}

Answer

anand picture anand · May 22, 2015

Haah.. Finally i got an answer to after an heck of losing almost 1 and half days. It might be not completely good answer but atleast it is one of the closest I got.

First of all MainActivity.java looks like:

 tabs.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            int scrollPosition = 0;
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if(position == 0){
                    scrollPosition = 0;
                }
                if(position == 1){
                    scrollPosition = 1;
                }
            }

            @Override
            public void onPageSelected(int position) {

            }

            @Override
            public void onPageScrollStateChanged(int state) {
                if(state == pager.SCROLL_STATE_IDLE){
                    if(scrollPosition == 0 && application.isActiveAction()){
                        viewPagerAdapter.notifyDataSetChanged();
                        application.setActiveAction(false);
                    }

                    if(scrollPosition == 1 && application.isArchiveAction()){
                        viewPagerAdapter.notifyDataSetChanged();
                        application.setArchiveAction(false);
                    }
                }
            }
        });

Now what I have done here is I have set OnPageChangeListener and in this I am keeping track of the position whenever the tabs are changing. For my needs what i have done is i have created two boolean variables and setting it when any content on those tab are changing in Application scope. Now when the contents on one tab has been changed or some Action are done I am calling

viewPagerAdapter.notifyDataSetChanged() // Now this is the real gem

after invoking this it will make a call to the ViewPagerAdapter function

@Override
    public int getItemPosition(Object object) {
        return PagerAdapter.POSITION_NONE;  // This will get invoke as soon as you call notifyDataSetChanged on viewPagerAdapter.
    }

Also the Point is your ViewPagerAdapter should extend FragmentStatePageAdapter. Now the Point is

PagerAdapter.POSITION_NONE

will not cache the fragment and reload a new fragment for that tab position. Basic idea is we should not make or retutn PagerAdapter.POSITION_NONE everytime on sliding of tab since it destroys the cached element and reload the fragment which affects UI performance.

So finally the basic thing is always check that whether on calling viewPagerAdapter.notifyDataSetChanged() the function getItemPosition() should also gets invoked. Hope it will help somebody. For better perfomance you can make changes according to your requirement.

I got the needed breakthrough and understanding from this post : @Louth Answer
Remove Fragment Page from ViewPager in Android