2

I have an horizontal ViewPager (let's call it A) that contains a fragment in each page. Each fragment has a vertical ViewPager (let's call it B) and each page contains a fragment with one image. When I scroll A to the right everything works fine but when I scroll to left (I guess in the moment the viewpager B is restored) the app crash and this is logcat info:

 01-09 09:55:06.802  25453-25453/com.test E/AndroidRuntime﹕ FATAL EXCEPTION: main
      Process: com.test, PID: 25453
    java.lang.NullPointerException
            at android.support.v4.app.FragmentState.instantiate(Fragment.java:94)
            at android.support.v4.app.FragmentManagerImpl.restoreAllState(FragmentManager.java:1790)
            at android.support.v4.app.Fragment.performCreate(Fragment.java:1489)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:893)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
            at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
            at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467)
            at android.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:472)
            at android.support.v4.app.FragmentStatePagerAdapter.finishUpdate(FragmentStatePagerAdapter.java:163)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:1068)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:914)
            at android.support.v4.view.ViewPager$3.run(ViewPager.java:244)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
            at android.view.Choreographer.doCallbacks(Choreographer.java:574)
            at android.view.Choreographer.doFrame(Choreographer.java:543)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)

Horizontal ViewPager A:

public class ScrollProductsFragment extends Fragment {

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    super.onCreateView(inflater, container, savedInstanceState);

    View view = inflater.inflate(R.layout.fragment_catalogue_scroll, container, false);
    ViewPager mViewPager = (ViewPager) view.findViewById(R.id.pager_details_pager);

    ...

    // load fragments
    ArrayList<Fragment> mListFragments = new ArrayList<Fragment>();
    for (Product product : listProducts) {
        mListFragments.add(ProductFragment.newInstance(product));
    }

    // setup viewpager
    MyStatePagerAdapter mPagerAdapter = new MyStatePagerAdapter(getChildFragmentManager(), mListFragments);
    mViewPager.setAdapter(mPagerAdapter);
    mViewPager.setSaveEnabled(false); 
    mViewPager.setCurrentItem(currentPage);
    mViewPager.setOffscreenPageLimit(2);

    ...
 }

ViewPager A and B use the same FragmentStatePagerAdapter

public class MyStatePagerAdapter extends FragmentStatePagerAdapter {

    private ArrayList<Fragment> list;

    public MyStatePagerAdapter(FragmentManager fm, ArrayList<Fragment> list) {
        super(fm);
        this.list = list;
    }

    @Override
    public Fragment getItem(int position) {
        return list.get(position);
    }

    @Override
    public int getItemPosition(Object object){
        return PagerAdapter.POSITION_NONE;
    }

    @Override
    public int getCount() {
        return list.size();
    }
}

ViewPager B:

 public class ProductFragment extends Fragment {

    private List<String> mListImages;
    private DirectionalViewPager mViewPager;

    public static final ProductFragment newInstance(Product product, String imageUrl) {
          ProductFragment fragment = new ProductFragment();
          Bundle bundle = new Bundle();
          bundle.putParcelable(EXTRA_PRODUCT, product);
          fragment.setArguments(bundle);
          return fragment;
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        super.onCreateView(inflater, container, savedInstanceState);

         this.mProduct = getArguments().getParcelable(EXTRA_PRODUCT);

        View view = inflater.inflate(R.layout.fragment_catalogue_product, container, false);
        mViewPager = (DirectionalViewPager) view.findViewById(R.id.detail_view_pager);

        // set adapter    
        ArrayList<Fragment> imageFragmentList = new ArrayList<Fragment>();    
        for(String image : mProduct.getImages()){
            imageFragmentList.add(ImageFragment.newInstance(image));
        }
        MyStatePagerAdapter pageAdapter = new MyStatePagerAdapter(getChildFragmentManager(),imageFragmentList);    

        // setup viewpager
        mViewPager.setOrientation(DirectionalViewPager.VERTICAL);
        mViewPager.setAdapter(pageAdapter);
        mViewPager.setSaveEnabled(false); 
        mViewPager.setOffscreenPageLimit(2);

        ...

        return view;
    }
}

Finally, the ImageFragment

public class ImageFragment extends Fragment {

    public static final ImageFragment newInstance(String imageUrl) {
        ImageFragment fragment = new ImageFragment();
        Bundle bundle = new Bundle();
        bundle.putString(EXTRA_URL, imageUrl);
        fragment.setArguments(bundle);
        return fragment;
    }



    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        super.onCreateView(inflater, container, savedInstanceState);

        String imageUrl = getArguments().getString(EXTRA_URL);

        View view = inflater.inflate(R.layout.fragment_image, container, false);
        ImageView imageView = (ImageView) view.findViewById(R.id.look_image);

        ImageLoader.getInstance().displayImage(imageUrl,imageView);

        return view;
    }

}

Thanks for your help.

esteban
  • 543
  • 4
  • 18

3 Answers3

2

Try to Use the this JakeWharton's library Android-DirectionalViewPager which supports paging both vertically and horizontally as well as changing between the two at runtime.

Gplay Link

enter image description here

Credits: JakeWharton

Community
  • 1
  • 1
LOG_TAG
  • 19,894
  • 12
  • 72
  • 105
0

It's hard to locate the issue by that logcat info. Your code looks ok for me. Maybe it helps to enable debug info in the FragmentManager:

getChildFragmentManager().enableDebugLogging(true);

By the way, I guess you copied a wrong constructor name (HorizontalStatePagerAdapter) in your MyStatePagerAdapter class. This shouldn't be the problem since you wouldn't be able to compile that code. ;)

Kirby
  • 86
  • 1
  • 8
  • No luck, the logcat shows the same information. About the name of the statePageAdapter, yes It was a wrong copy+paste. Thanks Kirby. – esteban Jan 10 '14 at 08:55
0

Though this is a very old question, I faced also same error.

I used FragmentStatePagerAdapter with normal FragmentManager. For some reason got same error as yours.

After doing many things I changed all thing to v4.* like v4.FragmentManager and v4.Fragment. Now its working fine. It's very wired solution & causing problem unknown.

Here is another solution I found which also working.

Community
  • 1
  • 1
Sayem
  • 4,891
  • 3
  • 28
  • 43