3

I started a new project using tabbed activity of Android Studio. It created an activity with ViewPager and 3 fragments = fragment1, fragment2 and fragment3. I changed fragment1 to have a listView and a TextView, that I initialize when the fragment is created. The data in the listView is read from an SQL database. When the application starts, fragment1 is displayed and the listView shows the data read from SQL. When I swipe from fragment1 to fragment2 and back, fragment1 shows the listview properly. However, when I swipe to fragment3 and back to fragment1 the listview data is lost and I get a blank screen, although the textview shows properly. When I change the application to have only 2 fragments it does not happen and I can swipe from fragment1 to fragment2 and back many times without any loss of data. The moment I add the 3rd fragment, the data is lost on first swipe to fragment3, but is not lost if I swipe between fragment 1 and fragment2 only. Any idea why is it happening?

Zvi
  • 2,354
  • 2
  • 26
  • 37
  • It's impossible to tell exactly why it's happening without a reproducible example. The reason the problem doesn't occur with two Fragments is that the FragmentPagerAdapter keeps both Fragments alive, see here: http://stackoverflow.com/questions/8348707/prevent-viewpager-from-destroying-off-screen-views and here: http://stackoverflow.com/questions/10853611/viewpager-with-fragments-onpause-onresume – Daniel Nugent Mar 02 '16 at 19:55
  • The project is too big to post. If we do not find a solution soon I will create a small version to post. – Zvi Mar 02 '16 at 22:15
  • The project is too big to post. If we do not find a solution soon I will create a small version to post. Anyway, I tested further and found out that what happens is that the listview lost its adapter (listView.getAdapter() returns null). So before the page is re-displayed I now test for this condition and if it exists I recreate the adapter, and the list is displayed properly. Can this give you a hint on what happens? – Zvi Mar 02 '16 at 22:22
  • Issue i snow solved. – Zvi Mar 10 '16 at 22:22

2 Answers2

4

This is happening because by default ViewPager has a function named setOffscreenPageLimit(int i). This tells ViewPager how many of the Fragments need to store in memory. By default it is '2'. So when you swipe to Fragment 2 from Fragment 1 it will still keep Fragment 1 in memory and won't destroy it from memory. But when you swipe to Fragment 3 it will have Fragment 2 and Fragment 3 in memory so it will remove Fragment 1.

That's why when you come back to your first Fragment it have lost its views or data.

Try to use

mViewPager.setOffscreenPageLimit(your total fragment count +1);

Or much better solution Do not replace your fragment when you swipe in ViewPager. Push it to the backstack and when you comeback to it, Check for the backstack and if fragment is there then just Pop it and display it.

Here is the code:

public void pushFragments(String tag, Fragment fragment) {
    FragmentManager manager = getSupportFragmentManager();
    FragmentTransaction ft = manager.beginTransaction();
    if (manager.findFragmentByTag(tag) == null) {
        ft.add(R.id.frame_container, fragment, tag);
    }
    String tagOne="com........Frag_one"; //your fragment class name
    String tagTwo="com........Frag_two";
    String tagThree="com........Frag_three";
    String tagFour="com........Frag_profile";

    Fragment fragmentOne = manager.findFragmentByTag(tagOne);
    Fragment fragmentTwo = manager.findFragmentByTag(tagTwo);
    Fragment fragmentThree = manager.findFragmentByTag(tagThree);
    Fragment fragmentFour = manager.findFragmentByTag(tagFour);
    manager.executePendingTransactions();
    // Hide all Fragment
    if (fragmentOne != null) {
        ft.hide(fragmentOne);
    }
    if (fragmentTwo != null) {
        ft.hide(fragmentTwo);
    }
    if (fragmentThree != null) {
        ft.hide(fragmentThree);
    }
    if (fragmentFour != null) {
        ft.hide(fragmentFour);
    }
    // Show  current Fragment
    if (tag.equals(tagOne)) {
        if (fragmentOne != null) {
            ft.show(fragmentOne);
        }
    }
    if (tag.equals(tagTwo)) {
        if (fragmentTwo != null) {
            ft.show(fragmentTwo);
        }
    }
    if (tag.equals(tagThree)) {
        if (fragmentThree != null) {
            ft.show(fragmentThree);
        }
    }
    if (tag.equals(tagFour)) {
        if (fragmentFour != null) {
            ft.show(fragmentFour);
        }
    }
    ft.commit();
}

And Here is how you call it:

Fragment fragment = new Frag_one();
pushFragments(fragment.getClass().getName(),fragment);
Zankrut Parmar
  • 1,872
  • 1
  • 13
  • 28
3

Issue solved. The problem is due to the adapter keeping 3 fragments in memory, as pointed by @Daniel Nugent. The data in the pages is loaded from DB so that when the view is recreated, when fragments are destroyed and recreated as the user swipes, the listview adapter has lost the data, and one has to repopulate it. The problem does not appear on simple examples because usually the data presented is static and is loaded in the onCreateView method.

Zvi
  • 2,354
  • 2
  • 26
  • 37