'“java.lang.IllegalStateException: Activity has been destroyed” after resuming the FragmentActivity on Android
I am using this approach: Separate Back Stack for each tab in Android using Fragments
I am trying to push fragment from first fragment, after resume the FragmentActivity this action causes the “Activity has been destroyed” error. When push fragment first time it works fine, but when I pause (minimize application) that FragmentActivity, re-open it and then try to push fragment, it gives the error. I know this question is already asked many times but I couldn’t get any solution from that.
Error
02-05 11:51:01.889: E/AndroidRuntime(379): FATAL EXCEPTION: main
02-05 11:51:01.889: E/AndroidRuntime(379): java.lang.IllegalStateException: Activity has been destroyed
02-05 11:51:01.889: E/AndroidRuntime(379): at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1365)
02-05 11:51:01.889: E/AndroidRuntime(379): at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
02-05 11:51:01.889: E/AndroidRuntime(379): at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:578)
02-05 11:51:01.889: E/AndroidRuntime(379): at com.app.main.AppMainTabActivity.pushFragments(AppMainTabActivity.java:650)
02-05 11:51:01.889: E/AndroidRuntime(379): at com.app.home.Home$ExpandableListAdapter$1.onClick(Home.java:530)
02-05 11:51:01.889: E/AndroidRuntime(379): at android.view.View.performClick(View.java:2408)
02-05 11:51:01.889: E/AndroidRuntime(379): at android.view.View$PerformClick.run(View.java:8816)
02-05 11:51:01.889: E/AndroidRuntime(379): at android.os.Handler.handleCallback(Handler.java:587)
02-05 11:51:01.889: E/AndroidRuntime(379): at android.os.Handler.dispatchMessage(Handler.java:92)
02-05 11:51:01.889: E/AndroidRuntime(379): at android.os.Looper.loop(Looper.java:123)
02-05 11:51:01.889: E/AndroidRuntime(379): at android.app.ActivityThread.main(ActivityThread.java:4627)
02-05 11:51:01.889: E/AndroidRuntime(379): at java.lang.reflect.Method.invokeNative(Native Method)
02-05 11:51:01.889: E/AndroidRuntime(379): at java.lang.reflect.Method.invoke(Method.java:521)
02-05 11:51:01.889: E/AndroidRuntime(379): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
02-05 11:51:01.889: E/AndroidRuntime(379): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
02-05 11:51:01.889: E/AndroidRuntime(379): at dalvik.system.NativeStart.main(Native Method)
I click expandable listview item in first fragment which push second fragment. I show the error in BaseExpandableListAdapter.
Push and Pop method in AppMainFragmentActivity
public void pushFragments(String tag, Fragment fragment, boolean shouldAnimate, boolean shouldAdd) {
if (shouldAdd) {
mStacks.get(tag).push(fragment);
}
if (!isFinishing()) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
if (shouldAnimate)
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left);
ft.replace(R.id.realtabcontent, fragment);
ft.commit();
}
else {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
if (shouldAnimate)
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left);
ft.replace(R.id.realtabcontent, fragment);
ft.addToBackStack(null);
ft.commitAllowingStateLoss();//error shows here also.
}
}
public void popFragments() {
/*if (!isFinishing()) { }*/
Fragment fragment = mStacks.get(mCurrentTab).elementAt(mStacks.get(mCurrentTab).size() - 2);
/*pop current fragment from stack.. */
mStacks.get(mCurrentTab).pop();
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
ft.replace(R.id.realtabcontent, fragment);
ft.commit();
}
Home Fragment
public class Firstfragment extends BaseFragment
{
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
private void setupActionBar() {
// TODO Auto-generated method stub
actionBar = getSherlockActivity().getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(false);
actionBar.setDisplayShowCustomEnabled(true);
actionBar.setDisplayShowHomeEnabled(false);
actionBar.setDisplayShowTitleEnabled(false);
View cView = getSherlockActivity().getLayoutInflater().inflate(R.layout.actionbarbutton, null);
final TextView cTitletext = (TextView) cView.findViewById(R.id.action_title_home);
final ImageButton cSection_Menu = (ImageButton) cView.findViewById(R.id.imgbtn_1);
actionBar.setCustomView(cView);
cSection_Menu.setImageResource(R.drawable.section);
cSection_Menu.setVisibility(View.VISIBLE);
cTitletext.setVisibility(View.VISIBLE);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.home_newspaper_list, container,false);
lv = (ExpandableListView) view.findViewById(R.id.newspapers_expandable);
setHasOptionsMenu(true);
return view;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
flag = true;
outState.putBoolean("flag", flag);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public void onPause() {
super.onPause();
flag = true;
AppConstants.isFromHomeDetailView = false;
index = lv.getFirstVisiblePosition();
}
@Override
public void onStop() {
// TODO Auto-generated method stub
super.onStop();
}
@Override
public void onResume() {
super.onResume();
lv.setSelectionFromTop(index, 0);
System.out.println(" onResume Started > "+flag);
setupActionBar();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
HashMap<String, ArrayList<HashMap<String,String>>> nlist = ma.newspaper_list;
ArrayList<String> languagelist = ma.languagelist;
expListAdapter = new ExpandableListAdapter(getActivity(), languagelist, nlist);
lv.setAdapter(expListAdapter);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return false;
}
public class ExpandableListAdapter extends BaseExpandableListAdapter
{
/* methods for BaseExpandableListAdapterlike getchildcount() etc. */
@Override
public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
View view = null;
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(final View v) {
secondfragment nl = new secondfragment ();
mActivity.pushFragments(AppConstants.TAB_A,nl,true, true);//****error on that line after resuming activity**.**
}
});
return view;
}
}
}
Solution 1:[1]
Looks like you are committing Fragment
when your FragmentActivity
is finishing and that causes the expection.
I would recommend to create mechanism to store the needed information of the Fragment
in that case and when your FragmentActivity
is alive and running and not finishing, then do the commit of Fragment
.
Solution 2:[2]
Besides writing ft.commitAllowingStateLoss();
you only need to write commit();
as the ft.commitAllowingStateLoss();
defines that
It is similar to commit() but allows the commit to be executed after an activity's state is saved. This is dangerous because the commit can be lost if the activity needs to later be restored from its state, so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.
So if you have destroyed your activity before then it will always throw Activity has been destroyed
error.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | GrIsHu |