34

Dostaję bardzo zagadkowy błąd, którego nie mam pojęcia, jak zacząć pracę.powoduje błąd java.IllegalStateException, brak aktywności, tylko podczas nawigacji do fragmentu na czas DRUGI

Mam prostą aplikację z jednym działaniem, widoki są realizowane za pomocą Fragmentów. Jeden z fragmentów ma wewnątrz ViewPagera; więc zdecydowałem, że chcę użyć klasy getChildFragmentManager biblioteki obsługi v4. Musiałem również użyć ActionBarSherlock, który spowodował problem, ponieważ nie jest wysyłany z v11 biblioteki v4.

Naprawiłem to, zastępując bibliotekę wsparcia v4 w systemie ABS biblioteką v11, a wszystko skompilowane i wydawało się działać, w tym ViewPager.

Oto dziwne część:

Po raz pierwszy fragment z ViewPager otwiera, to działa poprawnie; ale za DRUGI czas, w którym jest nawigowany, aplikacja ulega awarii, dając bezużyteczny ślad stosu. Z debugowania odkryłem, że problem polegał na tym, że FragmentManager został zwrócony przez getChildFragmentManager; Zgłasza błąd braku aktywności.

Czy ktoś ma pojęcie, co może być przyczyną?

Będę publikować kod, który uważasz za istotny.

Dziękuję Dawida

+0

proszę pisać wyjście pełny logcat –

+0

Czym dokładnie jest „brak aktywności "błąd? Jak w fragmencie nie jest dołączony do działania? Jaka jest linia kodu powodującego błąd? – Muz

Odpowiedz

45

Śledziłem link w jeremyvillalobos answer (co było bardzo pomocne), który doprowadził mnie do 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); 
      } 
     } 
    } 

    ... 
} 

To działa dla mnie dobrze, bez potrzeby przywracania fragmentu.

+0

Rozszerzyłem moje Fragmenty i działa jak urok. Rozwiązałem wiele problemów, które miałem od tak dawna! dobra robota. – ericosg

+0

To POWINNA BYĆ odpowiedź :) –

+0

Cześć ... to nie działa dla mnie .. mój kod jest tutaj: https://github.com/gbhola-bst/FragmentsTesting – gaurav414u

2

może twój błąd jest android.view.InflateException?

jeśli tak, powinieneś dynamicznie nadmuchać Fragment, nie używaj układu XML.

i nie należy kierować na fragment, który ma zdefiniowany układ XML do transakcji fragmentacji.

+0

nie, to nie był błąd. Naprawiłem to tymczasowo, zamiast zastępować, ukrywam i pokazuję. Nie jest idealny, ponieważ ta metoda może powodować problemy przy zmianie konfiguracji. – user1743524

2

Mam ten sam problem.

w działaniu, i ma 3 bouttons do przełączania fragment z transaction.replace (...)

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.layout_tablet_paneau, mLigneMessageFragment);

Jeden tego fragmentu zawierać ViewPage z niestandardowym FragmentPagerAdapter. Dlatego muszę zrobić getChildFragmentManager(), aby udostępnić zagnieżdżone Fragmenty.

konstruktor jest tutaj:

public LignePagerAdapter(Fragment ligneMessageTabletFragment) { 
     super(ligneMessageTabletFragment.getChildFragmentManager()); 
    } 

Więc mam ten sam błąd: Pierwszy pokaz tego fragmentu wrorks, ale kiedy pokazują inny fragment i wrócić na ten jeden, otrzymuję ten wyjątek:

 
02-26 11:57:50.798: D/ACRA(776): Wait for Toast + worker ended. Kill Application ? true 
02-26 11:57:50.798: E/AndroidRuntime(776): FATAL EXCEPTION: main 
02-26 11:57:50.798: E/AndroidRuntime(776): java.lang.IllegalStateException: No activity 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1075) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1070) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1861) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1474) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:931) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1088) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1444) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:429) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.os.Handler.handleCallback(Handler.java:587) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.os.Handler.dispatchMessage(Handler.java:92) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.os.Looper.loop(Looper.java:132) 
02-26 11:57:50.798: E/AndroidRuntime(776): at android.app.ActivityThread.main(ActivityThread.java:4126) 
02-26 11:57:50.798: E/AndroidRuntime(776): at java.lang.reflect.Method.invokeNative(Native Method) 
02-26 11:57:50.798: E/AndroidRuntime(776): at java.lang.reflect.Method.invoke(Method.java:491) 
02-26 11:57:50.798: E/AndroidRuntime(776): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844) 
02-26 11:57:50.798: E/AndroidRuntime(776): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) 
02-26 11:57:50.798: E/AndroidRuntime(776): at dalvik.system.NativeStart.main(Native Method) 
02-26 11:57:52.818: I/dalvikvm(776): threadid=4: reacting to signal 3 
02-26 11:57:52.818: I/dalvikvm(776): Wrote stack traces to '/data/anr/traces.txt' 

Zamiast wstawiać to samo wystąpienie fragmentu, mogę odtworzyć to, aby rozwiązać problem, ale wydaje mi się, że nie jest wydajne.

transaction.replace(R.id.layout_tablet_paneau, LigneMessageTabletFragment.newInstance()); 
23

Wydaje się to być błąd zgłaszać na

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

zmiennej

FragmentManagerImpl mChildFragmentManager;

W Fragment.java nie ma ustawionej wartości NULL na odłączeniu. Tak więc przy następnym wczytaniu fragmentu zmienna nadal wskazuje na ostatni element nadrzędny.

Jak omówiono w tym wątku, obejście polega na ponownym zainstalowaniu Fragmentu.

W moim przypadku przełączałem się między fragmentami w zakładce ActionBar. Zakłopotany Fragment zagnieździł Fragmenty i powodował awarię aplikacji po powrocie do Fragmentu modułu ładującego pliki. Więc to jest kod obejścia:

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

} 
3

niestety, jest to błąd wsparcia v4, nadal istnieje :(

Kiedy wybrać inny fragment poprzez panel nawigacji lub innych rzeczy, takich jak to, fragment, który ma sub-fragmenty są jednorodzinnych. Tak więc ci subfragmentów "fragmentManager (getChildFragmentManager()) już nie istnieje, podczas gdy te fragmenty wracają, wystąpił błąd Bomb!

Oczywiście, v4 powinien wyczyścić mChildFragmentManager w onDetach(), ale tak się nie stało, więc musimy polegać na sobie takie jak następujące kody w fragmencie, który zawiera pod-fragmenty:

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

Wszystko będzie OK, Miłego dnia :)

0

Patrz odpowiedź @lopisan:

używam jego rozwiązanie na długi czas.

ALE wymyśliłem lepszy sposób na zrobienie tego!

Jeśli parametr mChildFragmentManager.mActivity ma wartość null, ustaw dla mChildFragmentManager wartość null. Kiedy metoda performActivityCreated.

@Override 
void performActivityCreated(Bundle savedInstanceState) { 
    if (getFragmentManagerActivity(mChildFragmentManager) == null) { 
     setChildFragmentManager(this, null); 
    } 
    super.performActivityCreated(savedInstanceState); 
} 


public static FragmentActivity getFragmentManagerActivity(FragmentManager fragmentManager) { 
    FragmentManagerImpl fm = (FragmentManagerImpl) fragmentManager; 
    return fm.mActivity; 
} 



private static final Field sChildFragmentManagerField; 
static { 
    /** 
    * BUG : causing a java.IllegalStateException error, No Activity, only 
    * when navigating to Fragment for the SECOND time 
    * http://stackoverflow.com /questions/15207305/getting-the-error-java-lang-illegalstateexception-activity-has-been-destroyed 
    * http://stackoverflow.com/questions/14929907/causing-a-java-illegalstateexception-error-no-activity-only-when-navigating-to 
    */ 
    Field f = null; 
    try { 
     f = Fragment.class.getDeclaredField("mChildFragmentManager"); 
     f.setAccessible(true); 
    } catch (NoSuchFieldException e) { 
     Log.e(TAG, "Error getting mChildFragmentManager field", e); 
    } 
    sChildFragmentManagerField = f; 
} 

public static void setChildFragmentManager(Fragment fragment, FragmentManager fragmentManager) { 
    if (sChildFragmentManagerField != null) { 
     try { 
      sChildFragmentManagerField.set(fragment, fragmentManager); 
     } catch (Exception e) { 
      Log.e(TAG, "Error setting mChildFragmentManager field", e); 
     } 
    } 
} 
0

Utknąłem z tym samym błędem za pomocą przełącznika BottomNavigationView i zastąpieniem fragmentu powodującego awarię aplikacji. Z normalną prędkością to działa perfekcyjnie, jeśli użytkownik zrobić szybki przełącznik kiedyś upaść mówiąc

IllegalStateException No Activity

w logach

Przed mam

fragmentA = new FragmentA(); 
fragmentB = new FragmentB(); 
fragmentC = new FragmentC(); 

mBottomNavigationView.setOnNavigationItemSelectedListener(item -> { 
     switch (item.getItemId()) { 
    case R.id.fragmentA: 
     replaceFragment(fragmentA); 
    case R.id.fragmentB: 
     repalceFragment(fragmentB); 
    case R.id.fragmentC: 
     repalceFragment(fragmentC); 
    } 
}; 

myślę to wstępne tworzenie Fragment i używanie ich było zastępstwem, które tworzyło problem, teraz zrobiłem go, aby odtworzyć za każdym razem. Zaczęło działa dobrze

mBottomNavigationView.setOnNavigationItemSelectedListener(item -> { 
     switch (item.getItemId()) { 
    case R.id.fragmentA: 
     fragment = new FragmentA(); 
     replaceFragment(fragment); 
    case R.id.fragmentB: 
     fragment = new FragmentB(); 
     repalceFragment(fragment); 
    case R.id.fragmentC: 
     fragment = new FragmentC(); 
     repalceFragment(fragment); 
    } 
}; 

public void repalceFragment(Fragment fragment) { 
    if (!this.isFinishing()) { 
     if (!fragment.isAdded()) { 
      if (!this.mDisplayedFragment.isRemoving()) { 
       getFragmentManager().beginTransaction().replace(R.id.layout_fragment_container, fragment).commit(); 
       this.mDisplayedFragment = fragment; 
      } 
     } 
    } 
} 

Nadzieja jej pomocne dla niektórych, zrobiłem zbyt dużo kodowania obronnej ale to rozwiązać mój problem z szybkim przełączaniem fragmentów