2014-07-26 10 views
5

La mia app inizia con un AddressFragment. Dal NavigationDrawer comincio (tra gli altri) un nuovo AddressFragment con:Come conservare solo un'istanza di un frammento, quando si passa a NavigationDrawer?

getSupportFragmentManager().beginTransaction() 
       .replace(R.id.container, new AddressFragment()) 
       .addToBackStack(null) 
       .commit(); 

Ma preferirei solo tornare prima istanza. Come potrei farlo?

O più generale, come posso sapere se esiste già un'istanza di un frammento e quindi avviarlo, se sì, altrimenti crearne uno?

risposta

8

Quando si crea il frammento di impostare un tag per esso, poi si può trovare attraverso il frammento manager e sostituire/creare di conseguenza.

FragmentManager fManager = getFragmentManager(); 
FragmentTransaction fTransaction = fManager.beginTransaction(); 
Fragment fragment = fManager.findFragmentByTag("uniqueTag"); 

// If fragment doesn't exist yet, create one 
if (fragment == null) { 
    fTransaction.add(R.id.fragment_list, new ListFrag(), "uniqueTag"); 
} 
else { // re-use the old fragment 
    fTransaction.replace(R.id.fragment_list, fragment, "uniqueTag"); 
} 
2

La prima volta che crei il frammento con un tag.

Quando si desidera sostituirlo cercare di ottenere il frammento con la modifica e se tornare nulla si crea uno nuovo

4

Fase uno:

ottimizzare il codice corrente per consentire a un frammento di avere il proprio "TAG"

getSupportFragmentManager().beginTransaction() 
       .replace(R.id.container, new AddressFragment()) 
       .addToBackStack(**AddressFragment.class.getName()**) 
       .commit(); 

Fase due:

Da qualche parte nella vostra applicazione flusso è necessario per determinare se esiste un frammento:

public static boolean isFragmentInBackstack(final FragmentManager fragmentManager, final String fragmentTagName) { 
    for (int entry = 0; entry < fragmentManager.getBackStackEntryCount(); entry++) { 
     if (fragmentTagName.equals(fragmentManager.getBackStackEntryAt(entry).getName())) { 
      return true; 
     } 
    } 
    return false; 
} 

Fase tre:

eseguire l'azione frammento

if (exists) { 
    // Fragment exists, go back to that fragment 
    //// you can also use POP_BACK_STACK_INCLUSIVE flag, depending on flow 
    mFragmentManager.popBackStackImmediate(AddressFragment.class.getName(), 0); 

} else { 
    // Fragment doesn't exist 
    // STEP 1 + additional backstack management 
} 
+0

ho risolto con la soluzione per contrassegnare il frammento e non lo stack indietro. Sembra anche interessante, potrebbe provare un'altra volta. –

+0

Si scopre che Back restituisce in seguito un errore, se non si apre il backstack, quando si passa a un frammento esistente. Quindi, ho aggiunto un popBackStackImmediate, quando riutilizzavo un frammento esistente. –

+0

In caso di schiocco dello stack posteriore perderai "una istanza di un frammento", come l'autore desiderava – Androider

1

Questa risposta è testato, Spero che questo vi aiuterà a prima fare questi campi a livello globale in MainActivity

private static final int TIME_INTERVAL = 2000; 
private long mBackPressed; 
private FragmentManager fm; 
private FragmentTransaction ft; 
private DrawerLayout drawer; 

Ora, in onNavigationItemSelected() implementare come quello

@Override 
public boolean onNavigationItemSelected(MenuItem item) { 
Fragment fragment = null; 
Class fragmentClass = null; 
switch (item.getItemId()) { 
case R.id.nav_home: 
fragmentClass = Fragment.class;//this is MainAvctivty extends AppCompatActivity 
break; 
case R.id.nav_f1: 
fragmentClass = FragmentOne.class; 
break; 
case R.id.nav_f2: 
fragmentClass = FragmentTwo.class; 
break; 
case R.id.nav_f3: 
fragmentClass = FragmentThree.class; 
break; 
case R.id.nav_f4: 
fragmentClass = FragmentFour.class; 
break; 
case R.id.nav_f5: 
fragmentClass = FragmentFive.class; 
break; 
default: 
fragmentClass = Fragment.class; 
} 
try { 
fragment = (Fragment) fragmentClass.newInstance(); 
} catch (Exception e) {e.printStackTrace();} 
//Insert the fragment by replacing any existing fragment 
fm = getSupportFragmentManager(); 
ft = fm.beginTransaction(); 
ft.replace(R.id.frame_container, fragment); 
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
ft.addToBackStack(null); 
ft.commit(); 
item.setChecked(true); 
setTitle(item.getTitle()); 
drawer.closeDrawers(); 
return true; 
} 

ora gestire onbackpressed come qui di seguito

@Override 
public void onBackPressed() { 
if (drawer != null) { 
fm = getSupportFragmentManager(); 
ft = fm.beginTransaction(); 
if (drawer.isDrawerOpen(GravityCompat.START)) { 
drawer.closeDrawer(GravityCompat.START); 
} else if (fm.getBackStackEntryCount() > 0) { 
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); 
ft.commit(); 
} else if (mBackPressed + TIME_INTERVAL > System.currentTimeMillis()) { 
super.onBackPressed(); 
} else { 
Toast.makeText(this,"Press again to exit the app",Toast.LENGTH_SHORT).show(); 
} 
mBackPressed = System.currentTimeMillis(); 
} 
} 
Problemi correlati