7

I seem to be having an issue updating the fragments that I am using in my ViewPager, regardless of whether I try in onCreate(), onCreateView(), or onResume(). Here is how I'm setting up my ViewPager in my MainFragment:

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

        mPager = (ViewPager)rootView.findViewById(R.id.pager);
        mPager.setOffscreenPageLimit(2); // So all 3 pages are loaded at once.
        mAdapter = new JournalPagerAdapter(getActivity().getSupportFragmentManager(), this);
        mPager.setAdapter(mAdapter);

        // Add bar graph to view
        mGraphLayout = (LinearLayout) rootView.findViewById(R.id.journalGraph);
        updateGraph();
        mGraphLayout.addView(mGraphView);

        mPainFrag = (PainFragment)mAdapter.getRegisteredFragment(0);
        // Null pointer here, but if I put the action in a button listener, it works.
        mPainFrag.setScale(mEntry.getPain());
...

I'm accessing the fragments through some overridden methods in my FragmentPagerAdapter:

public class JournalPagerAdapter extends FragmentPagerAdapter {

    SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
    private View.OnClickListener mOnClickListener;


    public JournalPagerAdapter(FragmentManager mgr, View.OnClickListener onClickListener) {
        super(mgr);
        mOnClickListener = onClickListener;
    }
    @Override
    public Fragment getItem(int pos) {
        switch(pos) {

            case 0: return PainFragment.newInstance("PainFragment", mOnClickListener);
            case 1: return StressFragment.newInstance("StressFragment", mOnClickListener);
            case 2: return SleepFragment.newInstance("SleepFragment", mOnClickListener);
            default: return PainFragment.newInstance("PainFragment", mOnClickListener);
        }
    }

    @Override
    public int getCount() {
        return 3;
    }

    /* Thanks to Streets of Boston (http://stackoverflow.com/questions/8785221/retrieve-a-fragment-from-a-viewpager)
    */

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Log.v("rx", "itemInstantiated");
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }

    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }

I can't seem to figure out why the fragment is null right after I set the adapter, but if I put the fragment update code in a click event, I have no issues.

jwBurnside
  • 849
  • 4
  • 31
  • 66
  • Did you try to make a Runnable to let the time for the ui to create the ViewPager? – Blo Apr 15 '14 at 18:15
  • I thought about that in my initial experimentation, but I'd rather use a runnable as a last resort. I don't think I'm doing anything out of the ordinary here, it sounds logical that there would be a way to notify the host fragment of the FragmentPagerAdapter being fully initialized. – jwBurnside Apr 15 '14 at 19:45
  • I don't think you have the choice because you select the fragment with mAdapter.getRegisteredFragment (and it's an inner method from your adapter). Then, I think you must wait the adapter. – Blo Apr 16 '14 at 14:03
  • your first fragment is not iniated so what about second fragment? – CompEng Apr 18 '14 at 07:37
  • @jwburnside you say if Iput the framgent update code in a click event , where are your update code in the beginning? – CompEng Apr 18 '14 at 07:38

2 Answers2

8

I would try adding a layout listener to your ViewPager to get notified when the laying out of views has occurred.

When you create your ViewPager call mPager.getViewTreeObserver().addOnGlobalLayoutListener() and pass something implementing OnGlobalLayoutListener.

In the callback method, do your fragment updating. Make sure to call mPager.getViewTreeObserver().removeGlobalOnLayoutListener(this) in the callback, otherwise the callback will be called multiple times.

dandc87
  • 1,096
  • 5
  • 7
0

You could instantiate your fragments in the PagerAdapter's constructor and just have getItem return them instead of instantiating them.

nbarraille
  • 9,926
  • 14
  • 65
  • 92