Getting the Error "Java.Lang.Illegalstateexception Activity Has Been Destroyed" When Using Tabs With Viewpager

Getting the error Java.lang.IllegalStateException Activity has been destroyed when using tabs with ViewPager

This seems to be a bug in the newly added support for nested fragments. Basically, the child FragmentManager ends up with a broken internal state when it is detached from the activity. A short-term workaround that fixed it for me is to add the following to onDetach() of every Fragment which you call getChildFragmentManager() on:

@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);
}
}

Getting the error: java.lang.IllegalStateException: Activity has been destroyed when doing notifyDataSetChanged for viewPager adapter

Whenever you access the instance variable or context with Delay or in a callback you should check for its existence first.

For Activity

Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if(!isFinishing())
mViewPager.getAdapter().notifyDataSetChanged();
}
}, 1000);

For fragment

Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if(isAdded())
mViewPager.getAdapter().notifyDataSetChanged();
}
}, 1000);

ChildFragmentManager java.lang.IllegalStateException: Activity has been destroyed

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");

IllegalStateException: Activity has been destroyed (API level 21)

Found a solution here:
Getting the error "Java.lang.IllegalStateException Activity has been destroyed" when using tabs with ViewPager Its a known bug in android.

You have to override the onDetach() in the Fragments that use the childFragmentManager and set its reference to null.

override fun onDetach() {
super.onDetach()

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
try {
val childFragmentManager = Fragment::class.java!!.getDeclaredField("mChildFragmentManager")
childFragmentManager.setAccessible(true)
childFragmentManager.set(this, null)

} catch (e: NoSuchFieldException) {
throw RuntimeException(e)
} catch (e: IllegalAccessException) {
throw RuntimeException(e)
}
}
}

java.lang.IllegalStateException: Activity has been destroyed

This is know issue look here

This is a bug in the nested fragments. Basically, the child FragmentManager ends up with a broken internal state when it is detached from the activity.

A short-term workaround is to add the following code in your fragment.

@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);
}
}

Handling Activity has been destroyed (java.lang.IllegalStateException) exception?

As a general rule, an Android context should be stored as little as possible and used only when needed.

If you're getting null or invalid exceptions when trying to use the Activity context, that means you're performing operations outside the standard Android lifecycle of an Activity.

Due to the nature of the lifecycle (asynchronous), it's sometimes really hard to predict when these situations will arise… unless, you avoid performing operations outside the lifecycle events where the context is guaranteed to be alive.

E.g.: Performing Activity/Context operations in onPostExecute methods of asynctasks or even threads, is a time bomb.

As a general rule, before attempting to use an Activity/Context outside the lifecycle methods (onResume for example), is also dangerous and should always be accompanied by a null check.

I used to have a simple method to check this:

if (activity != null && !activity.isFinishing()) {
// safe
}

After Jelly Bean (API 17 afaik) you can also check activity.isDestroyed() or similar (can't remember now).

If you have to store a context (to later perform some context related action), always try to store the Application Context (activity.getApplicationContext()) which is a static reference to the Application singleton and it won't leak.

That being said, keep in mind what limitations each type of context has. When in doubt, keep a bookmark to this around, specially to understand why trying to inflate layouts with an Application context may yield unexpected results.

UPDATE:

If you need a common/generic place to operate on your Fragments, keep a handy util class around like (pseudo code):

public final class FragmentUtils {
private FragmentUtils() {
}
public static void add(FragmentActivity fragmentActivity, int layoutId, Fragment fragment) {
if (isContextInvalid(fragmentActivity)) {
return
}
FragmentTransaction fragmentTransaction = fragmentActivity.getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(layoutId, fragment);
fragmentTransaction.commit();
}

public static void replace(FragmentActivity fragmentActivity, int layoutId, Fragment fragment) {
if (isContextInvalid(fragmentActivity)) {
return
}
// TODO: you do this one ;)

}

public static void remove(FragmentActivity fragmentActivity, Fragment fragment) {
if (isContextInvalid(fragmentActivity)) {
return
}
// TODO: you do this one ;)
if (fragment.isAdded()) {

}
}

public static void show(FragmentActivity fragmentActivity, Fragment fragment) {
// TODO: you do this one ;)
if (fragment.isAdded()) {

}
}

public static void hide(FragmentActivity fragmentActivity, Fragment fragment) {
// TODO: you do this one ;)
if (fragment.isAdded()) {

}
}
public boolean isContextInvalid(final Context context) {
if (context == null || context.isFinishing()) {
return true;
}
return false;
}
}

And add the null/checks to your context there. (Or similar)
Note the above code is not complete, I just wrote it here in this editor….

java.lang.IllegalStateException: Activity has been destroyed

This is know issue look here

This is a bug in the nested fragments. Basically, the child FragmentManager ends up with a broken internal state when it is detached from the activity.

A short-term workaround is to add the following code in your fragment.

@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);
}
}


Related Topics



Leave a reply



Submit