Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

causing a java.IllegalStateException error, No Activity, only when navigating to Fragment for the SECOND time

I am getting a very puzzling bug that I have no idea how to even begin working through.

I have a simple app with one activity, the views are implemented with Fragments. One of the fragments has a ViewPager inside of it; so I decided I that I wanted to use the getChildFragmentManager class of the v4 support library. I also had to use ActionBarSherlock, which caused a problem, because it does not ship with the v11 of the v4 library.

I fixed this by replacing the v4 support library in ABS with the v11 library, and everything compiled and appeared to be working, including the ViewPager.

Here is the strange part:

The first time the fragment with the ViewPager opens, it works properly; but the SECOND time it is navigated to, the app crashes, giving a useless stack trace. From debugging, I discovered that the problem was with the FragmentManager returned by getChildFragmentManager; it throws the No Activity error.

Does anybody have any idea what could be causing this?

I will post code that you think is relevant.

Thank you, David

like image 465
user1743524 Avatar asked Feb 18 '13 05:02

user1743524


People also ask

Which method is called when a fragment is not connected to the activity?

The onActivityCreated() method is called after onCreateView() and before onViewStateRestored() . onDestroyView() : Called when the View previously created by onCreateView() has been detached from the Fragment . This call can occur if the host Activity has stopped, or the Activity has removed the Fragment .


2 Answers

I followed the link in jeremyvillalobos answer (which was very helpful) that led me to this workaround.

public class CustomFragment extends Fragment {     private static final Field sChildFragmentManagerField;      static {         Field f = null;         try {             f = Fragment.class.getDeclaredField("mChildFragmentManager");             f.setAccessible(true);         } catch (NoSuchFieldException e) {             Log.e(LOGTAG, "Error getting mChildFragmentManager field", e);         }         sChildFragmentManagerField = f;     }      @Override     public void onDetach() {         super.onDetach();          if (sChildFragmentManagerField != null) {             try {                 sChildFragmentManagerField.set(this, null);             } catch (Exception e) {                 Log.e(LOGTAG, "Error setting mChildFragmentManager field", e);             }         }     }      ... } 

It works for me well, without the need to reinstantiate the fragment.

like image 93
lopisan Avatar answered Oct 26 '22 12:10

lopisan


This appears to be a bug reported at

https://code.google.com/p/android/issues/detail?id=42601

The variable

FragmentManagerImpl mChildFragmentManager;

In Fragment.java is not set to null on detach. So the next time the fragment is loaded, the variable still points to the last parent.

As discussed on that thread, a workaround is to reinstantiate the Fragment.

In my case, I was switching between fragments in an ActionBar tab. The troubled Fragment has nested Fragments and was crashing the app when coming back to the file loader Fragment. So this is the work-around code:

class MainTabsListener implements ActionBar.TabListener {     public Fragment fragment;     public int TabPosition;      public MainTabsListener(Fragment fragment, int tab_position) {         this.fragment = fragment;         TabPosition = tab_position;     }      @Override     public void onTabReselected(Tab tab, FragmentTransaction ft) {     }      @Override     public void onTabSelected(Tab tab, FragmentTransaction ft) {         CurrentFragment = fragment;         CurrentTabSelectedPos = TabPosition;          /**          * This is a work-around for Issue 42601          * https://code.google.com/p/android/issues/detail?id=42601          *           * The method getChildFragmentManager() does not clear up          * when the Fragment is detached.          */         if( fragment instanceof FileLoaderFragment ){             fragment = reinstatiateFileLoaderFragment();         }          ft.replace(R.id.fragment_container, fragment);      }      @Override     public void onTabUnselected(Tab tab, FragmentTransaction ft) {         ft.remove(fragment);     }  } 
like image 40
jeremyvillalobos Avatar answered Oct 26 '22 12:10

jeremyvillalobos