1

I'm using a FragmentPagerAdapter to create a 3 page viewpager and up until I upgraded to sdk 23 it worked fine. I am using one fragment and sending in different args depending on the getItem(position) to populate different data. After the upgrade Android isn't acknowledging one of the pages and I have to got to position 2 (page 3) and then slide back to position 0 (page 1) and then Android populates the page with the correct data. Running thru the debugger confirmed that Android skips over case 2 in the getItem function in TabAdapter.java. I am also getting W/FragmentManager: moveToState: Fragment state for TabContentFragment{3ac2d125 #3 id=0x7f0f0097} not updated inline; expected state 3 found 2. I've been using this similar question as reference but still couldn't get it to work but I have cornered the problem down to the FragmentManager I am using. But after messing with it for hours I haven't been able to get Android to see that there are 3 pages not 2.

TabAdapter.java

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

import com.movies.R;
import com.movies.date.LiveStatus;
import com.movies.fragments.TabContentFragment;
import com.movies.fragments.TabFragment;
import com.movies.utils.BundleKeys;

public class TabAdapter extends FragmentPagerAdapter {

private Context context;

public TabAdapter(FragmentManager fm, Context context) {
    super(fm);
    this.context = context;
}

/**
 * Return fragment with respect to Position .
 */

@Override
public Fragment getItem(int position) {
    TabContentFragment fragment = new TabContentFragment();
    Bundle args = new Bundle();
    switch (position){
        case 0:
            args.putInt(BundleKeys.STATE_KEY, LiveStatus.EVENT_STARTED);
            break;
        case 1:
            args.putInt(BundleKeys.STATE_KEY, LiveStatus.EVENT_NOT_STARTED);
            break;
        case 2:
            args.putInt(BundleKeys.STATE_KEY, LiveStatus.EVENT_OVER);
            break;
    }
    fragment.setArguments(args);
    return fragment;
}

@Override
public int getCount() {
    return TabFragment.MAX_TABS;
}

/**
 * This method returns the title of the tab according to the position.
 */

@Override
public CharSequence getPageTitle(int position) {

    switch (position) {
        case 0:
            return this.context.getString(R.string.tab_title_live);
        case 1:
            return this.context.getString(R.string.tab_title_upcoming);
        case 2:
            return this.context.getString(R.string.tab_title_replay);
        default:
            return null;
        }
    }
}

Data from bundle is pulled like this

this.state = getArguments().getInt(BundleKeys.STATE_KEY);

TabFragment.java

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.movies.R;
import com.movies.adapters.TabAdapter;

public class TabFragment extends Fragment {

public static final int MAX_TABS = 3;
public static TabLayout tabLayout;
public static ViewPager viewPager;

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    /**
     * Inflate tab_layout and setup Views.
     */
    View view = inflater.inflate(R.layout.tab_layout, null);
    tabLayout = (TabLayout) view.findViewById(R.id.tabs);
    viewPager = (ViewPager) view.findViewById(R.id.event_info_viewpager);

    /**
     * Set an Adapter for the View Pager
     */
    viewPager.setAdapter(new TabAdapter(getFragmentManager(), getContext()));

    /**
     * Now , this is a workaround ,
     * The setupWithViewPager doesn't works without the runnable .
     * Maybe a Support Library Bug .
     */

    tabLayout.post(new Runnable() {
        @Override
        public void run() {
            tabLayout.setupWithViewPager(viewPager);
        }
    });
    return view;
    }
}

Activity that Holds the TabFragment starts fragment like this:

mFragmentManager = getSupportFragmentManager();
    mFragmentTransaction = mFragmentManager.beginTransaction();
    mFragmentTransaction.replace(R.id.container_view, new TabFragment()).commit();
Community
  • 1
  • 1
Jay Syko
  • 71
  • 2
  • 6

1 Answers1

1

I'm not sure if I am understanding your question correctly or not but it sounds to me like your last (third) tab isn't being created until you navigate to it.

By default, the ViewPager is limited to creating only 2 off screen views (one to the left and one to the right). Typically, apps start off in the left most tab, meaning, if you have 3 in total, the right most tab will not be created until you navigate closer to it.

You can override this in your MainActivity by using ViewPager.setOffScreenPageLimit(#) where ViewPager is actually the name of your ViewPager and # is the number of tabs you want to create from the start. In your case it sounds like you want this number to be 2.

Joel Nieman
  • 746
  • 4
  • 13
  • when the app starts it starts on page 1 but the information that should be on it isn't there but if I swipe all the way to the right (the last page) the info for the last page shows up and then when I scroll back to page 1 the info for page 1 shows up. And it's not a network latency sorta thing because I would leave the app on page 1 for 5 minutes and nothing happens and then works once I go to page 3 and then go back to page 1 – Jay Syko Jun 07 '16 at 14:03
  • If you can show the code for the specific fragment's controller I can take a look at it. Are you using any AsyncTasks on your first fragment? – Joel Nieman Jun 07 '16 at 14:08
  • no asynctasks in use. the way it starts up is when the hosting activity starts tabfragment (see bottom of post) TabFragment inflates the views and starts the tabadapter which then starts up tabcontentfragment and passes different pieces of data depending on the position of the page. – Jay Syko Jun 07 '16 at 14:27
  • Sounds like you aren't saving the arg to the bundle until the fragment is destroyed (i.e., onDestroy or onPause, etc.) when you scroll all the way over to the right (when you are on the far right, the first tab is destroyed because the view pager will only hang on to the tabs directly next to it). When you scroll back to the first tab it is recreated and will use the arguments saved in the savedInstanceState if you set this up. – Joel Nieman Jun 07 '16 at 14:42