Search code examples
androidandroid-fragmentsandroid-viewpager

Viewpager fragments not shown after the first time


I have an activity with 3 fragments (A, B, C). Fragment A consists of a ViewPager with 2 ListFragments. The user can tap on an item in any of the listfragments and by doing so, goes to fragment B.

In fragment A I do:

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    pagerAdapter = new PagerAdapter(getActivity().getSupportFragmentManager());
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragmentA, container, false);

    vpPager = (ViewPager)view.findViewById(R.id.vpPager);
    vpPager.setOffscreenPageLimit(2);
    vpPager.setAdapter(pagerAdapter);
    vpPager.addOnPageChangeListener(this);

    return view;
}

And the PagerAdapter is as follows:

private class PagerAdapter extends FragmentPagerAdapter {
    private final ListFragment1 lf1 = ListFragment1 .newInstance();
    private final ListFragment2 lf2 = ListFragment2 .newInstance();

    public PagerAdapter(android.support.v4.app.FragmentManager fm) {
        super(fm);
    }

    @Override
    public android.support.v4.app.Fragment getItem(int position) {
        switch (position) {
            case 0:  return lf1;
            case 1:  return lf2;
            default: return null;
        }
    }
}

The first time the activity is shown, the viewpager list fragments are displayed correctly.

The 2 viewpager fragments load data from a db, and I do this only once (when the fragments are created).

The user can tap on an item and fragment B is displayed. If the user presses Back, fragment A is shown. However the list fragments are not shown (already an instance of them still exists).

Could it be that the view has been destroyed, even though instances exist?

What is wrong here? Is there a better approach?

EDIT

If I use newInstance in the pager adapter, I get an IllegalStateException: not attached to activity. This is because I start an async task as follows:

@Override
public void onPageSelected(int position) {
    Fragment fragment = pagerAdapter.getItem(position);
    if (fragment instanceof IPagedFragment) {
        ((IPagedFragment) fragment).onShown();
    }
}

And onShown is:

@Override
public void onShown() {
    myTask= new MyTask();
    myTask.execute((Void)null);
}

When can I start the task so that I can be 100% sure that the fragment is attached to the activity and that the view has been created (I need to get listview, etc. from the layout).


Solution

    1. On PagerAdapter class override the method setPrimaryItem, which is called when there's a change in the pager, i would give it a shot.

    I would create something like :

     private class PagerAdapter extends FragmentPagerAdapter {
            private final ListFragment1 lf1 = ListFragment1 .newInstance();
            private final ListFragment2 lf2 = ListFragment2 .newInstance();
    
            public PagerAdapter(android.support.v4.app.FragmentManager fm) {
                super(fm);
            }
    
            @Override
            public android.support.v4.app.Fragment getItem(int position) {
                switch (position) {
                    case 0:  return lf1;
                    case 1:  return lf2;
                    default: return null;
                }
            }
    
            @Override
            public int getCount() {
                return 2;
            }
    
            @Override
            public void setPrimaryItem(ViewGroup container, int position, Object object) {
                super.setPrimaryItem(container, position, object);
                if (position == 0)
                    lf1.updateUI(); //Refresh what you need on this fragment
                else if (position == 1)
                    lf2.updateUI();
            }
    
        }
    
    1. You're missing getCount() as well.
    2. I'm not sure offscreen has any use, but its probably not an issue. vpPager.setOffscreenPageLimit(2)
    3. One more thing, i would also remove vpPager.addOnPageChangeListener(this), there's no use for this, an it might cause you some issues. Whatever you need to do, you can pull it off without it, by overriding the pagination, you might "ruin" some of the standard pagination(since the super isn't called)