I'm currently developing an app which uses a TabLayout with a ViewPager, and have the following problem: sometimes, without any recognizable pattern, the onPageSelected(int position) is called. This is an issue, because the app saves the previous section when moving to a new one, and saving implies validating fields. So whenever the onPageSelected is randomly called, the position is that of the first section (0), and that view has not been created, so trying to validate EditTexts will result in a NPE.
Since this app is under NDA, I'll try to give as many hints to the code as possible, without getting fired (:
The app has a main FragmentActivity
which handles the ViewPager
, and the onPageSelected
method.
Each section is a Fragment (v4 Support Library), and is instantiated in the onPageSelected method, using Fragment page = (Fragment) viewPager.getAdapter().instantiateItem(viewPager, savedFragmentPosition)
.
The ViewPager
has a custom FragmentStatePagerAdapter
, which basically calls a SectionNFragment fragment = new SectionNFragment()
, where N is the position+1.
But, after a random amount of time, the onPageSelected
is called again, and the app crashes. Whenever this occurs, the ViewPager
tries to show the first Fragment, Section1Fragment
, then return to the currently displayed one.
This means that the position goes from N to 0, then back to N, but crashes in the middle, because it tries saving the Section1Fragment
.
My team and I have tried replicating this bug, but after 2 weeks of trying to find a pattern, we have concluded it is random. We have tried:
- Alternating between FragmentStatePagerAdapter and FragmentPagerAdapter.
- Only saving when the fragment is not null and visible, but this brings up another issue, where the main Object we're using becomes null for some reason. This is only a workaround, not a solution per se.
- Saving each section Fragment at the Fragment's onDestroy, but this brings up usability issues, since the last few sections would have to be saved manually (they wouldn't be destroyed, because of the ViewPager's
setOffscreenPageLimit
is 1 at its minimum, so those would be kept in memory).
Has anyone else encountered this issue? I apologize for being this vague, but StackOverflow is my last resort.
Thanks in advance, any sort of insight would be helpful!
EDIT 1
I decided to add some code related to the viewPager's creation within the FragmentActivity (called FormActivity)'s onCreate:
viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new FormFragmentPagerAdapter(getSupportFragmentManager(),
FormActivity.this));
viewPager.addOnPageChangeListener(this);
// Give the TabLayout the ViewPager
tabLayout = (TabLayout) findViewById(R.id.sliding_tabs);
tabLayout.setupWithViewPager(viewPager);
EDIT 2
I wanted to clear up the fact that this bug is not device-specific. I have tried this app and the bug happens in two different devices, with two different versions of Android: a 2012 Nexus 7 running 5.1.1, and a Huawei MediaPad T1 8.0 Pro running 4.4.2.