Ramprasad Ramprasad - 3 months ago 4
Java Question

ChildFragmentManager java.lang.IllegalStateException: Activity has been destroyed

I have tried to add a fragment inside another fragment inside viewpager using

getChildFragmentManager()
. I got following error,


java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1549)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:654)
at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:625)
at com.lakeba.gameon.userprofile.UserProfileContainerFragment.replaceFragment(UserProfileContainerFragment.java:72)


And I tried this workaround but still getting same error.

UserProfileContainerFragment.java

public class UserProfileContainerFragment extends CustomFragment {


private View rootView;
private Fragment fragment1;

public UserProfileContainerFragment() {
// Required empty public constructor
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}

public static UserProfileContainerFragment newInstance() {
UserProfileContainerFragment fragment = new UserProfileContainerFragment();
return fragment;
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
rootView = inflater.inflate(R.layout.fragment_user_profile_container, container, false);

if(savedInstanceState == null) {
UserProfileFragment userProfileFragment = UserProfileFragment.newInstance();
getChildFragmentManager().beginTransaction()
.replace(R.id.user_profile_container, userProfileFragment)
.commitAllowingStateLoss();
}

return rootView;
}

/*@Override
public void onSaveInstanceState(Bundle outState) {
//super.onSaveInstanceState(outState);
}*/

public void replaceFragment(Fragment fragment, boolean addToBackStack){
fragment1 = fragment;
if(addToBackStack){
/*getChildFragmentManager().beginTransaction()
.replace(R.id.user_profile_container, fragment)
.addToBackStack(null)
.commit();*/
getChildFragmentManager().beginTransaction()
.replace(R.id.user_profile_container, fragment)
.addToBackStack(null)
.commit();
//.commitAllowingStateLoss();
}
else{
getChildFragmentManager().beginTransaction()
.replace(R.id.user_profile_container, fragment)
.commit();
//.commitAllowingStateLoss();
}

}

@Override
public void onDetach() {
super.onDetach();

try {
Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
childFragmentManager.setAccessible(true);
childFragmentManager.set(this, null);

} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}

}
}


HomeMapActivity.java

public class HomeMapActivity extends AppCompatActivity implements UserProfileFragment.OnUserProfileFragmentListener{

private Toolbar homeToolbar;
private ViewPager homeViewPager;
private TabLayout homeTabLayout;
private UserProfileContainerFragment userProfileContainerFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_map);

/*homeToolbar = (Toolbar) findViewById(R.id.home_toolbar);
setSupportActionBar(homeToolbar);

getSupportActionBar().setDisplayHomeAsUpEnabled(true);*/

homeViewPager = (ViewPager) findViewById(R.id.home_view_pager);

HomeViewPagerAdapter homeViewPagerAdapter = new HomeViewPagerAdapter(getSupportFragmentManager());
userProfileContainerFragment = new UserProfileContainerFragment();
homeViewPagerAdapter.addFragment(new UserProfileContainerFragment(),"Profile");
homeViewPager.setAdapter(homeViewPagerAdapter);

homeTabLayout = (TabLayout) findViewById(R.id.home_tabs);
homeTabLayout.setupWithViewPager(homeViewPager);
setTabIcons(homeTabLayout);


homeTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int tabPosition = tab.getPosition();
tab.setIcon(tabIconsArrayActivated[tabPosition]);
}

@Override
public void onTabUnselected(TabLayout.Tab tab) {
int tabPosition = tab.getPosition();
tab.setIcon(tabIconsArray[tabPosition]);
}

@Override
public void onTabReselected(TabLayout.Tab tab) {
int tabPosition = tab.getPosition();
tab.setIcon(tabIconsArrayActivated[tabPosition]);
}
});

homeTabLayout.getTabAt(1).select();
}

private void setTabIcons(TabLayout homeTabLayout) {
homeTabLayout.getTabAt(0).setIcon(tabIconsArray[0]);
homeTabLayout.getTabAt(1).setIcon(tabIconsArray[1]);
homeTabLayout.getTabAt(2).setIcon(tabIconsArray[2]);
homeTabLayout.getTabAt(3).setIcon(tabIconsArray[3]);
}

@Override
public void onUserProfileEditButtonClicked() {
userProfileContainerFragment.replaceFragment(EditUserProfileFragment.newInstance(),true);
}

private class HomeViewPagerAdapter extends FragmentStatePagerAdapter{

private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();

public HomeViewPagerAdapter(FragmentManager fm) {
super(fm);
}

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

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

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

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

Answer

If you look at the code in your onCreate() method you'll see the lines:

userProfileContainerFragment = new UserProfileContainerFragment();
homeViewPagerAdapter.addFragment(new UserProfileContainerFragment(),"Profile");

You first initialize the userprofileContainerFragment field with a new instance of UserProfileContainerFragment and then right below you create a new instance of UserProfileContainerFragment to be used in the ViewPager(you can easily observe this by placing a log statement in the constructor of UserProfileContainerFragment...you'll see two instances being created). Later in your code you try to use the field userProfileContainerFragment which will lead to a failure as that instance of UserProfileContainerFragment is not attached to the activity at all(this isn't the fragment used by the ViewPager).

Your code should look like below, to maintain the proper reference and not create detached fragments:

userProfileContainerFragment = new UserProfileContainerFragment();
homeViewPagerAdapter.addFragment(userProfileContainerFragment,"Profile");
Comments