Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I am getting crash in my Viewpager when I open the parent fragment for second time

Tags:

Some Information: I have a fragment which contains a viewpager with three fragments. First time when I open this fragment viewpager works. second time I try to open this fragment then it crashes with following stacktrace

NOTE: This is happening on kitkat above 19 API its working fine

ViewPager setup code inside parent fragment

private void setupViewPager(ViewPager viewPager) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        adapter = new ViewPagerAdapter(getChildFragmentManager());
    } else {
        adapter = new ViewPagerAdapter(getFragmentManager());
   }
    adapter.addFrag(fragment1 , "Abc");
    adapter.addFrag(fragment2, "Bcd");
    adapter.addFrag(fragment3, "Cdf");

    viewPager.setAdapter(adapter);
    viewPager.setOffscreenPageLimit(2);

    myTabs.setupWithViewPager(viewPager);
}

My viewpager Adapter

class ViewPagerAdapter extends android.support.v13.app.FragmentPagerAdapter {
    private final List<android.app.Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public android.app.Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return super.getItemId(position);
    }


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

    public void addFrag(android.app.Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }
}

Here is the crash stacktrace:

10-14 21:23:47.276 17601-17601/com.d.p E/AndroidRuntime: FATAL EXCEPTION: main
  Process: com.d.p, PID: 17601                                                     
java.lang.IllegalStateException: No activity
   at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1049)
   at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1044)
   at android.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1853)
   at android.app.Fragment.performActivityCreated(Fragment.java:1714)
   at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:908)
   at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
   at android.app.BackStackRecord.run(BackStackRecord.java:684)
   at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1447)
   at android.app.FragmentManagerImpl$1.run(FragmentManager.java:443)
   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)
like image 434
Ritzor Avatar asked Oct 14 '17 16:10

Ritzor


1 Answers

Finally Resolved
This is the bug in native fragments and also support v4.

When you choose other Fragment via Navigation Drawer or other thing like it, the fragment which has sub-fragments is detached. So those sub-fragments' fragmentManager(getChildFragmentManager()) is no longer exist. while those fragments return, it crashes.

So basically we will need to clean mChildFragmentManager in onDetach(). So just put below code in the fragment which is having nested fragments.

 @Override
 public void onDetach() {
    try {
        Field childFragmentManager = android.app.Fragment.class.getDeclaredField("mChildFragmentManager");
        childFragmentManager.setAccessible(true);
        childFragmentManager.set(this, null);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    super.onDetach();
   }

Source Google issue Tracker

like image 131
Ritzor Avatar answered Oct 11 '22 13:10

Ritzor