8

In my app i am using navigation tab using view pager. I have able to successfully drawn the tabs using the code posted on:

https://github.com/codepath/android_guides/wiki/Sliding-Tabs-with-PagerSlidingTabStrip

Here i have used the Sliding tab and view pager both to get the navigation tabs.Everything is working fine but the list are not getting updated when i am moving to the other tab. OnResume() is getting called even the Object list variable is also getting updated while debugging but visually list is not getting updated.

Here i am some snippets of the code:

For Tab1 : which in my case is ACTIVE tab

 @Override
    public void onResume() {
        super.onResume();

        if(!internetUtil.isConnectedToInternet(getActivity())){
            mSwipeRefreshLayout.setEnabled(false);
        }else{
            mSwipeRefreshLayout.setEnabled(true);
            new GetUsersFromServerTask().execute();  // Here i am making the network calls 
        }
}

On Tab2 : Which is Archive tab

 @Override
    public void onResume() {
        super.onResume();
        new GetUsersArchivedFromServerTask().execute(); // Network calls
    }

In MainActivity:

public class MaterialTab extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.material_main_sample);
        ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
        viewPager.setAdapter(new SampleFragmentPagerAdapter(getSupportFragmentManager()));
        PagerSlidingTabStrip tabsStrip = (PagerSlidingTabStrip) findViewById(R.id.tabs);
        tabsStrip.setViewPager(viewPager);
        tabsStrip.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
            @Override
            public void onPageSelected(int position) {
                if(position == 0){
                   ActiveFragment activeFragment = new ActiveFragment();
                    final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                    ft.detach(activeFragment);
                    ft.attach(activeFragment);
                    ft.commit();
                } if(position == 1){
                    ArchiveFragment archiveFragment = new ArchiveFragment();
                    final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                    ft.detach(archiveFragment);
                    ft.attach(archiveFragment);
                    ft.commit();
                }
            }
        });
    }
}

Also the thing is when i am doing SwipeRefresh then the List is getting updated. I am now totally confused why this behaviour. When i am swiping the tab the same methods are getting called and thelist is not getting updated but when I am doing SwipeRefresh it's getting Updated.

This is the Active Fragment:

public class ActiveFragment extends Fragment {

public void updateFragment(){
        new GetUsersArchivedFromServerTask().execute();
    }

 public class GetUsersArchivedFromServerTask extends AsyncTask<User, Void, String> {
        @Override
        protected String doInBackground(Shipment... parmas) {
            // Log.d(TAG, String.valueOf(shipmentDbHandler.getAllActiveShipments().size()));
            _userList1 = userDbHandler.getAllActiveUserByToday(DateTimeUtil.getCurrentTime());
            return "";
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(String str) {
            // Set the refresh Listener to false after the list has been loaded with new set of data
            if (mSwipeRefreshLayout.isRefreshing()) {
                mSwipeRefreshLayout.setRefreshing(false);
            }

            if(_userList1.size() == 0){
                ViewGroup parentOne = (ViewGroup) viewOne.getParent();
                if(parentOne != null){
                    parentOne.removeView(viewOne);
                }
            }

            if(_shipmentList1.size() > 0 ){
                mShipmentAdapter = new ShipmentAdapter(getActivity(),_userList1,1); 
                shipmentListView1.setAdapter(mShipmentAdapter);
                setListViewHeightBasedOnChildren(shipmentListView1);
                ViewGroup parentOne = (ViewGroup) viewOne.getParent();
                if(parentOne == null){
                    mainLayoutOne.addView(viewOne);
                }

                mShipmentAdapter.notifyDataSetChanged();
            }
            mSwipeRefreshLayout.setClickable(true);
        }
    }
}   
anand
  • 1,711
  • 2
  • 24
  • 59

7 Answers7

4

PLease use FragmentStatePagerAdapter for that.

  • 1
    view pager loads side fragment also, so onResume method will called already , so when you swipe to that fragment then onResume not called again – Anand Makwana May 14 '15 at 08:15
3

Your OnPageChangeListener is screwing with the fragments. Every time a page is selected you create a new Fragment and always add it.. your trying to detach a new Fragment that's not attached yet. Its completely messed up. Your SampleFragmentPagerAdapter will handle those fragment transactions for you. So just remove your setOnPageChangeListener and everything should be fine.

Simon
  • 10,932
  • 50
  • 49
3

Here is a simple and working solution for you. Just replace setOnPageChangeListener like this, here we're accessing the instance of current fragment with the help of getSupportFragmentManager and making call to respective fragment method.

    tabsStrip.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            Fragment currentFragment = getSupportFragmentManager()
                    .findFragmentByTag(
                            "android:switcher:" + R.id.viewpager + ":"
                                    + mViewPager.getCurrentItem());
            if (currentFragment instanceof ActiveFragment) {
                ((ActiveFragment) currentFragment).updateFragment();
            } else if (currentFragment instanceof ArchiveFragment) {
                ((ArchiveFragment) currentFragment).updateFragment();
            }
        }
    });

And inside your respective fragment put updateFragment() method.

public void updateFragment() {
    Toast.makeText(getActivity(), "ActiveFragment", Toast.LENGTH_SHORT)
            .show();
    // make updates over here
    // new GetUsersArchivedFromServerTask().execute(); // Network calls
}

Reference link.

Community
  • 1
  • 1
Chitrang
  • 5,097
  • 1
  • 35
  • 58
  • I tried this approach but its giving null pointer exception for rest of the elements – anand May 27 '15 at 06:45
  • What do you mean by "rest of the elements"? – Chitrang May 27 '15 at 07:27
  • rest of the elements means in the layout i have swipeRefresh .. buttons then all those are giving null pointer exception – anand May 27 '15 at 08:41
  • I request you to put that fragment class in your question, so that we can have clear idea. – Chitrang May 27 '15 at 09:39
  • i have posted the fragment code ... I can't put the whole code , I have posted snippets of the ActiveFragment – anand May 27 '15 at 09:58
  • It's difficult find what's causing you NPE without looking at your code you might be missing something for passing in async class. And I didn't get idea of viewOne.getParent() what this is? It'll be good if you provide full source code of fragment class. – Chitrang May 27 '15 at 10:07
2
  1. remove onPageSelected(...) codes from page change listerner, no need attatch/detatch manually, ViewPager take care this automatically. And also your SampleFragmentPagerAdapter should create each Fragment instance in getItem(...).

  2. new GetUsersFromServerTask().execute() should be called in each Fragment's onCreateView and then update the view after Asynctask done.


Besides, you should be aware of OffscreenPageLimit:

public void setOffscreenPageLimit (int limit)

Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state. Pages beyond this limit will be recreated from the adapter when needed.

This is offered as an optimization. If you know in advance the number of pages you will need to support or have lazy-loading mechanisms in place on your pages, tweaking this setting can have benefits in perceived smoothness of paging animations and interaction. If you have a small number of pages (3-4) that you can keep active all at once, less time will be spent in layout for newly created view subtrees as the user pages back and forth.

You should keep this limit low, especially if your pages have complex layouts. This setting defaults to 1.

Xcihnegn
  • 11,579
  • 10
  • 33
  • 33
  • I have removed attach and detach of the fragment but now no method is getting called inside the fragment. I think it's caching those fragments. – anand May 28 '15 at 08:06
  • Actually `ViewPager` always keep neighbors in caching, which means neighbors got calling togather with current Fragment. So when you move to neighbor, you could not see it is updating, actually it already updated. – Xcihnegn May 28 '15 at 08:18
1

Use this inside your fragment.

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if (isVisibleToUser) {
        // Do your code here
    }
}

This method is called every time when the tab is visible to user. Hope this will solve your problem!!!!

Sandeep Singh
  • 1,117
  • 2
  • 11
  • 29
0

Try to use notifyDataChange or notifyall

parik dhakan
  • 787
  • 4
  • 19
0

Override setPrimaryItem() and call a refresh() method of your fragment at the position. setPrimaryItem() is called every time the selected item changes in viewPager. It may be called more than once so you have to handle it too. see: setPrimaryItem

I hope this helps.

Ercan
  • 3,705
  • 1
  • 22
  • 37