5

Ich habe eine Aktivität und mit einer Schaltfläche, die ich zwischen den beiden Fragmenten (MAIN & SETTINGS) wechseln. Im MAIN-Fragment habe ich eine ViewPager mit 4 Kindfragmenten.Android Kindfragmente von Viewpager getActivity gibt Null

Beim ersten Lauf funktioniert alles gut, aber wenn ich den Bildschirm drehen, gibt getActivity() für Fragmente innerhalb der ViewPager Null zurück.

ActivityMain:

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

    // Add or show the fragments 
    showHideScreenFragment(FRAGMENT_MAIN); 
} 

private void showHideScreenFragment(String tag) { 

    FragmentManager fm = getSupportFragmentManager(); 
    FragmentTransaction ft = fm.beginTransaction(); 

    ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); 

    // Get the fragment from the backstack if it is existing 
    BaseFragment oldFragment = getFragmentFromBackstack(tag); 

    // Get the current fragment from the layout 
    BaseFragment currentFragment = getCurrentFragment(); 

    if (oldFragment == null) { 
     if (currentFragment != null) { 
      ft.hide(currentFragment); 
     } 

     ft.add(getMainContainerId(), getFragmentInstance(tag), tag); 
    } 
    else { 

     if (currentFragment != null) { 
      if (isSameFragment(oldFragment, currentFragment)) 
       return; 

      ft.hide(currentFragment); 
     } 

     if (oldFragment.isHidden()) 
      ft.show(oldFragment); 
    } 

    ft.commit(); 
    fm.executePendingTransactions(); 
} 

private BaseFragment getFragmentInstance(String tag) { 
    if (tag.equals(FRAGMENT_MAIN)) return getFragmentMain(); 
    if (tag.equals(FRAGMENT_SETTINGS)) return getFragmentSettings(); 

    throw new RuntimeException("Fragment not found !"); 
} 

private FragmentMain getFragmentMain() { 
    return new FragmentMain(); 
} 

private FragmentSettings getFragmentSettings() { 
    return new FragmentSettings(); 
} 

private BaseFragment getFragmentFromBackstack(String tag) { 
    if (tag.equals(FRAGMENT_MAIN)) return getFragmentMainFromBackstack(); 
    if (tag.equals(FRAGMENT_SETTINGS)) return getFragmentSettingsFromBackstack(); 

    throw new RuntimeException("Fragment not found !"); 
} 

private FragmentMain getFragmentMainFromBackstack() { 
    return (FragmentMain) getSupportFragmentManager().findFragmentByTag(FRAGMENT_MAIN); 
} 

private FragmentSettings getFragmentSettingsFromBackstack() { 
    return (FragmentSettings) getSupportFragmentManager().findFragmentByTag(FRAGMENT_SETTINGS); 
} 

private boolean isSameFragment(Fragment f1, Fragment f2) { 
    return f1.getTag().equals(f2.getTag()); 
} 

FragmentMain:

@Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {   
     View view = inflater.inflate(R.layout.fragment_main, container, false); 

     viewPager = (ViewPager) view.findViewById(R.id.viewPager); 

     // Add the 4 child fragments to the viewpager 
     populateViewPager(); 

     // Debugging 
     new Handler().postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       _printFragmentStates(); 
      } 
     }, 2500); 

     return view; 
    } 

    private void populateViewPager() {  
     ArrayList<BaseMainFragment> fragments = new ArrayList<BaseMainFragment>(); 

     fragments.add(new FragmentSearch()); 
     fragments.add(new FragmentFavorites()); 
     fragments.add(new FragmentHouse()); 
     fragments.add(new FragmentRoom()); 

     adapterMain = new AdapterMain(getChildFragmentManager(), fragments); 

     viewPager.setOffscreenPageLimit(4); 
     viewPager.setAdapter(adapterMain); 
    } 

    // DEBUGGING 
    private void _printFragmentStates() { 
     Activity actSearch = null; 
     Activity actFav = null; 
     Activity actHouse = null; 
     Activity actRoom = null; 

     actSearch = getFragmentSearch().getActivity(); 
     actFav = getFragmentFavorites().getActivity(); 
     actHouse = getFragmentHouse().getActivity(); 
     actRoom = getFragmentRoom().getActivity(); 

     Functions.logd("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 
     Functions.logd("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 
     Functions.logd("Main fragment act, is null: " + (getActivity() == null)); 
     Functions.logd("Search act, is null: " + (actSearch == null)); 
     Functions.logd("Favorite act, is null: " + (actFav == null)); 
     Functions.logd("House act, is null: " + (actHouse == null)); 
     Functions.logd("Room act, is null: " + (actRoom == null)); 
     Functions.logd("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 
     Functions.logd("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); 
} 

private FragmentSearch getFragmentSearch() { 
    return (FragmentSearch) adapterMain.getItem(0); 
} 

private FragmentFavorite getFragmentFavorite() { 
    return (FragmentFavorite) adapterMain.getItem(1); 
} 

private FragmentHouse getFragmentHouse() { 
    return (FragmentHouse) adapterMain.getItem(2); 
} 

private FragmentRoom getFragmentHouse() { 
    return (FragmentRoom) adapterMain.getItem(3); 
} 

Wie gesagt, zunächst alles funktioniert gut laufen, aber nachdem ich den Bildschirm drehen, ich bin immer null für getActivity(); in den 4 Kindfragmenten: Suche, Favorit, Haus und Zimmer.

Logcat debug

1 laufen:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
Main fragment act, is null: false 
Search act, is null: false 
Favorite act, is null: false 
House act, is null: false 
Room act, is null: false 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Nach Bildschirmausrichtung geändert:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
Main fragment act, is null: false 
Search act, is null: true 
Favorite act, is null: true 
House act, is null: true 
Room act, is null: true 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Was mache ich falsch?

Antwort

0

Es ist eine gute Praxis, ein Muster wie diese zu folgen, wenn sie mit Fragmenten arbeiten:

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    return inflater.inflate(R.layout.fragment, container, false); 
} 

@Override 
public void onViewCreated(View view, Bundle savedInstanceState) { 
    super.onViewCreated(view, savedInstanceState); 
    view = view.findViewById(R.id.view); 
} 

@Override 
public void onActivityCreated(@Nullable Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
// do your thing here 
populateViewPager(); 
} 

1) OnCreateView Verwenden Sie Ihr Fragment Ansicht zu setzen, 2) OnViewCreated Ansicht und 3) OnActivityCreated Setup zu initialisieren Dinge.

Mit getActivity() innerhalb OnActivityCreated wird sichergestellt, dass getActivity() nicht Null zurückgibt. Diese Methode wird erst aufgerufen, nachdem die Aktivität vollständig initialisiert wurde. OnAttach, OnCreate, OnCreateView möglicherweise noch bevor die Aktivität erstellt wird.

2

Nach stundenlangem Debugging habe ich herausgefunden, dass Sie, wenn Sie nur ein Fragment (ohne Kind oder verschachtelte Fragmente) an Ihre Aktivität angehängt haben, Ihr Fragment nicht erneut hinzufügen müssen.

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

    // Add or show the fragments if the savedInstance is null, otherwise let the system reattach your fragment. 
    if (savedIstance == null) 
     showHideScreenFragment(FRAGMENT_MAIN); 
} 

Sie nicht das Fragment wieder anbringen müssen, das Android-System wird dies für Sie tun.

Und die Lösung für NPE bei getActivity(); in Kind-Fragmenten erhalten ist:

Verwenden FragmentStatePagerAdapter für Ihre ViewPager ‚s-Adapter.

und überschreiben die gespeicherten Zustand Methode:

@Override 
public Parcelable saveState() { 
    return null; 
} 

Ich weiß nicht, warum, aber setRetainInstance(false); hat mir nicht geholfen, und ich denke, das ist ein Rätsel für mich bleiben.

Verwandte Themen