5

Ho un'attività e con un pulsante sto passando tra due frammenti (MAIN & Impostazioni). Nel frammento MAIN ho uno ViewPager con 4 frammenti figlio.childfragments Android di viewpager getActivity restituisce null

Al primo avvio, tutto funziona correttamente, ma se si ruota lo schermo,per frammenti all'interno dello ViewPager restituisce null.

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

Come ho già detto, in un primo momento gestiscono tutto funziona bene, ma dopo che ho ruotare lo schermo, sto ottenendo nullo per getActivity(); nei 4 frammenti figli: Cerca, Preferiti, Casa e Stanza.

Logcat di debug

1 run:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
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 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Dopo orientamento dello schermo è cambiato:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
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 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

Che cosa sto facendo di sbagliato?

risposta

0

E 'una buona pratica di seguire un modello come questo, quando si lavora con i frammenti:

@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) Utilizzare OnCreateView per impostare vista del frammento, 2) OnViewCreated per inizializzare vista e 3) OnActivityCreated da installare cose.

L'utilizzo di getActivity() all'interno di OnActivityCreated assicura che getActivity() non restituisca null. Questo metodo viene chiamato solo dopo che l'attività è stata completamente inizializzata. OnAttach, OnCreate, OnCreateView potrebbe arrivare anche prima della creazione dell'attività.

2

Dopo ore di debug, ho capito che se si ha solo un frammento (senza frammenti figlio o nidificati) collegato alla propria attività, non è necessario aggiungere nuovamente il frammento.

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

Non è necessario riattaccare il frammento, il sistema Android farà questo per voi.

E la soluzione per ottenere NPE a getActivity(); in frammenti bambino è:

Usa FragmentStatePagerAdapter per l'adattatore S' tuoi ViewPager.

e l'override del metodo stato salvato:

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

Non so perché, ma setRetainInstance(false); non mi ha aiutato, e credo che questo rimarrà un mistero per me.

Problemi correlati