6

I have a viewpagerindicator by Jake Wharton and in that viewpager i have 6 pages.All of the pages contains listviews and i'm loading them with an AsyncTask.Sometimes viewpager shows wrong pages at wrong indexes.Here is my viewpager adapter:

public class TestFragmentAdapter extends FragmentPagerAdapter{
    protected static final String[] CONTENT = new String[] { "a","b","c","d","e","f" };

    private int mCount = CONTENT.length;
    Fragment fragment1,fragment2,fragment3,fragment4,fragment5,fragment6;

    public TestFragmentAdapter(FragmentManager fm) {
        super(fm);
        fragment1 = new CategoryListView();
        fragment2 = CustomizedListviewRecent.newInstance(41);
        fragment3 = CustomizedListviewMostRecents.newInstance(0);
        fragment4 = CustomizedListviewPopulars.newInstance();
        fragment5 = CustomizedListviewRecent.newInstance(42);
        fragment6 = CustomizedListviewRecent.newInstance(43);

    }

    @Override
    public Fragment getItem(int position) {
        if(position == 0)
            return fragment1;
        else if(position == 1)
            return fragment2;
        else if(position == 2)
            return fragment3;
        else if(position == 3)
            return fragment4;
        else if(position == 4)
            return fragment5;
        else
            return fragment6;
    }
    @Override
    public int getCount() {
        return mCount;
    }

    @Override
    public CharSequence getPageTitle(int position) {
      return TestFragmentAdapter.CONTENT[position % CONTENT.length];
    }

    public void setCount(int count) {
        if (count > 0 && count <= 10) {
            mCount = count;
            notifyDataSetChanged();
        }
    }

}

Here is how i create my viewpager:

public class SampleTitlesDefault extends BaseSampleActivity {

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

        mAdapter = new TestFragmentAdapter(getSupportFragmentManager());

        mPager = (ViewPager)findViewById(R.id.pager);
        mPager.setAdapter(mAdapter);

        mIndicator = (TitlePageIndicator)findViewById(R.id.indicator);
        mIndicator.setViewPager(mPager);
        mIndicator.setCurrentItem(1);
    }

}

What can be problem here?How can i solve this?Thanks for your help

droidmachine
  • 577
  • 2
  • 8
  • 24
  • I'm having a similar issue! I'm also using ViewPageIndicator and Fragments. Hmmm, what could be the issue here? I'm going to have a look at my code and see what's up – Jade Byfield Jan 26 '13 at 19:16
  • I removed the ViewPageIndicator from my XML and from my activity code. Problem still persists. My fragment activity seems to confuse which fragment is the current one, and when I try to add an item to a gridview that's on fragment(page) 4 for instance...it gets added to the list on fragment 1 instead. Looking deeper into things hopefully we both can get some help on this one. – Jade Byfield Jan 26 '13 at 19:22
  • @JadeByfield Are you using .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) to execute your AsyncTask in your fragments? – droidmachine Jan 29 '13 at 20:32
  • No, I'm not. I'm not doing any background operations inside my fragments just inflating a gridview and populating it. I have 4 fragments like this, but sometimes when I try to add an item to the gridview of one, it get's added to another! – Jade Byfield Jan 29 '13 at 20:47
  • @JadeByfield Is your adapter same with my adapter? – droidmachine Jan 29 '13 at 20:56
  • Yes, I also use FragmentPagerAdapter. Any suggestions? – Jade Byfield Jan 29 '13 at 20:59
  • Try to use:FragmentStatePagerAdapter instead of FragmentPagerAdapter.Also use it like in David's answer.Lastly,override destroyItem like that: public void destroyItem(ViewGroup paramViewGroup, int paramInt, Object paramObject){ super.destroyItem(paramViewGroup, paramInt, paramObject); } – droidmachine Jan 29 '13 at 21:06
  • Thanks for the tips man. I've switched to now using a FragmentStatePagerAdapter as well as overriding destroyItem...still the same problem. Tinkering around with some stuff to see what's up. Have you solved your problem yet? – Jade Byfield Jan 29 '13 at 22:04
  • Hi Anyone got the problem to this solution . ? I also facing the same problem .Page count is not right. – Bora Aug 07 '13 at 07:37

2 Answers2

3

I know its too late but may be some one need it.

I have also faced the similar problem regarding wrong position and some time it shows same results on two fragments due to wrong positon.I solved my problem by replacing the FragmentPagerAdapter with FragmentStatePagerAdapter

And I also passed index postion from onPageScrolled method using OnPageChangeListener inteface

 viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {


        }

        @Override
        public void onPageSelected(int position) {

            bundle = new Bundle();
            bundle.putInt("position", position);
            primaryFragment.setCurrentPostionAndData(position);

        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });

Like the docs say, think about it this way. If you were to do an application like a book reader, you will not want to load all the fragments into memory at once. You would like to load and destroy Fragments as the user reads. In this case you will use FragmentStatePagerAdapter. If you are just displaying 3 "tabs" that do not contain a lot of heavy data (like Bitmaps), then FragmentPagerAdapter might suit you well. Also, keep in mind that ViewPager by default will load 3 fragments into memory. The first Adapter you mention might destroy View hierarchy and re load it when needed, the second Adapter only saves the state of the Fragment and completely destroys it, if the user then comes back to that page, the state is retrieved.

Difference between FragmentPagerAdapter and FragmentStatePagerAdapter

Community
  • 1
  • 1
abubaker
  • 319
  • 3
  • 7
0

Please don't "cache" the Fragments yourself because it already does that for you.

That said, you should newInstance them inside the getItem method, and not when creating the adapter. Example:

public TestFragmentAdapter(FragmentManager fm) {
    super(fm);
}

@Override
public Fragment getItem(int position) {
    if(position == 0)
        return new CategoryListView();
    else if(position == 1)
        return CustomizedListviewRecent.newInstance(41);
    else if(position == 2)
        return CustomizedListviewMostRecents.newInstance(0);
    else if(position == 3)
        return CustomizedListviewPopulars.newInstance();
    else if(position == 4)
        return CustomizedListviewRecent.newInstance(42);
    else
        return CustomizedListviewRecent.newInstance(43);
}

Common reasons to do that are:

  1. People think it's more efficient to do it that way; or
  2. A reference to the Fragment may be needed later on.

For (1), as I said, you don't need to worry about it (unless you want to learn it and tweak later, but for now let it be). And if you need (2), then you can do this (originally seen here).

Community
  • 1
  • 1
davidcesarino
  • 16,160
  • 16
  • 68
  • 109
  • Thanks for your reply.I also tried that but i'm still having that problem.Is there a bug in ViewPager? – droidmachine Jan 29 '13 at 12:07
  • Sometimes my first two pages are same.Normally they must have completely different pages. – droidmachine Jan 29 '13 at 16:10
  • @droidmachine none that I'm aware of. I'd suggest reducing your code and implementing the complexities at each step (improve-test-improve-test-repeat...). Remember that keeping track and changing the count is not even necessary (the adapter class can be much smaller). Hopefully it's not something wrong with your Fragments that look like a problem in the viewpager (e.g., Fragments displaying the same content before your AsyncTasks load them all). Try starting from scratch with demo Fragments and fixed layout contents. – davidcesarino Jan 29 '13 at 21:28