0

In an Android app, I have a dynamic viewPager, that may display a dynamic number of fragment (the fragment number is fixed before its instantiation). This viewPager is composed of 4 (fixed number) subViewPager. Every subViewPager can hold 1-5 fragments. It means that the whole count of fragment can reach up to 20 items.

For Info : A fragment can be just a set of fields, up to a canvas driven view, where the user interact with touching, added with bitmap displaying

I tried a first implementation by using a FragmentPagerAdapter (for main and subs viewpagers), it worked fine, but it took to much memory (120 MB of allocated heap memory)

I’m now using a FragmentStatePagerAdater to decrease the memory allocation

My problem, is that the subViewPager, which is handled in the Fragment of the mainViewPager, may be killed over navigation (this is what expected by statepageradapter to free memory) (they are initialized in OnCreateView).

=> The point is that I need that object to be able to swipe with a button :

For passing to the next fragment, I need to access to the mainViewPager, then the subViewPager of the current item of the mainViewPager in order to inc the current visible fragment.

The issue is that the holding fragment of the subViewPager may be/is killed, so the viewPager is null. Where and how handle the subviewpager to enable accessing subviewpager PLUS enable freeing memory by killing the unvisible fragments.

Here is a code part :

public class MySubViewPagerFragment extends Fragment {

    private MySubFragmentPagerStateAdapter mSubPagerStateAdapter;
    private ViewPager mPagerSub;
    private TitlePageIndicator mIndicatorSub;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.vp_sub, container, false);

        int id = getArguments().getInt("id");

        // Creation de l'adapter
        mSubPagerStateAdapter = new MySubFragmentPagerStateAdapter(getChildFragmentManager(), ((MainActivity) getActivity()).getConfigList().get(id));
        // Creation du Pager
        mPagerSub = (ViewPager) v.findViewById(R.id.vp_sub);
        // Affectation de l'adapter au ViewPager
        mPagerSub.setAdapter(this.mSubPagerStateAdapter);

        TitlePageIndicator indicator = (TitlePageIndicator) v.findViewById(R.id.tpi_sub);
        indicator.setViewPager(mPagerSub);
        mIndicatorSub = indicator;
        return v;
    }

    public boolean swipNextFragment() {
        boolean result = false;
        int c = mPagerSub.getCurrentItem();
        if (c < (mPagerSub.getAdapter().getCount() - 1)) {
            result = true;
            new Handler().post(new Runnable() {
                @Override
                public void run() {
                    mPagerSub.setCurrentItem(mPagerSub.getCurrentItem() + 1);
                }
            });

        }
        return result;
    }
}

I have tried to put the subViewPager at the activity level, but nothing has been solved.

Do you had any commun use case / solution or advise ?

Here is an example project with the same architecture. https://github.com/afaucogney/NestedAndroidViewPagers

PS: feel free to push me some advice on other optimisation if you see some.

Anthony
  • 3,989
  • 2
  • 30
  • 52
  • From what I understood from your question the culprit is the line `MySubViewPagerFragment frag = (MySubViewPagerFragment) mMainPagerStateAdapter.getItem(c);`(in the activity from the project to which you linked to). Calling `getItem()` will get you a **new** instance of the fragment and **not** the one you think the adapter is currently using. That new instance doesn't have it's callbacks called so also it doesn't have a view etc. Instead of `getItem()` you may want to call `mMainPagerStateAdapter.instantiate(mPagerMain, c)`. – user Apr 26 '15 at 11:11
  • you means mMainPagerStateAdapter.instantiateItem(mPagerMain, c) ? If yes, that worked better, but it poped another issues propably linked with missing usage of finishUpdate http://developer.android.com/reference/android/support/v13/app/FragmentStatePagerAdapter.html#finishUpdate(android.view.ViewGroup) – Anthony Apr 27 '15 at 11:40
  • Can you explain what happens when using what I said above? – user Apr 27 '15 at 11:43
  • I get java.lang.NullPointerException at fr.millezimu.app.nestedviewpager.Activity.Adapter.MySubFragmentPagerStateAdapter.getCount(MySubFragmentPagerStateAdapter.java:37). This is the getCount implementation @Override public int getCount() { return config.getChildFragments().size(); }. But I feel that when I'm in debug, it is not happening, because I feel a process succeed to do something. This is always the same error, but never happening at the same fragment index. – Anthony Apr 27 '15 at 13:19
  • Just wait, maybe something else. Could you explain me instanciateItem / getItem (=> new instance). Does the wording is not missused ? – Anthony Apr 27 '15 at 13:35
  • Ok he does work. Thank you. My aim is to decrease the most the memory, so releasing the whole objects memory referenced in the fragment that are not viewed (main and sub). Is there something else to do ? – Anthony Apr 27 '15 at 13:51
  • You should avoid ViewPagers in ViewPagers especially as you seem to swipe between all of the inner pages before switching to another main fragment. Maybe you could lose the inner pages and just do one big ViewPager containing all the inner pages. – user Apr 27 '15 at 14:54
  • Your advice is because of complexity, or just because it would be easier ? – Anthony Apr 27 '15 at 15:45
  • Both. Just think that with one big ViewPager you'll have just 3 sub pages loaded at any time versus your current situation when you have loaded at every moment 3 main fragments(along with all their sub fragments). Of course I'm speaking without knowing what the content is, but if it fits I really think you should consider a single ViewPager. – user Apr 27 '15 at 17:05

0 Answers0