2012-05-23 17 views
9

ho un'attività con sotto la layoutFragment.isAdded restituisce vero dopo frammento rimosso da un contenitore

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="horizontal" > 

    <FrameLayout 
     android:id="@+id/frameLayoutA" 
     android:layout_width="wrap_content" 
     android:layout_height="fill_parent" 
     android:layout_weight="1" > 
    </FrameLayout> 
    <FrameLayout 
     android:id="@+id/frameLayoutB" 
     android:layout_width="wrap_content" 
     android:layout_height="fill_parent" 
     android:layout_weight="1" > 
    </FrameLayout> 
</LinearLayout> 

In onCreate di attività, carico Fragment_A in frameLayoutA e Fragment_B in frameLayoutB.

public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    fmA=(FrameLayout) findViewById(R.id.frameLayoutA); 
    fmB=(FrameLayout) findViewById(R.id.frameLayoutB); 

    fragA=new FragmentA(); 
    fragB=new FragmentB(); 
    fragC=new FragmentC(); 
    addFragmentsInActivity(R.id.frameLayoutA,fragA); 
    addFragmentsInActivity(R.id.frameLayoutB,fragB); 
} 

public void addFragmentsInActivity(int id, Fragment fragment) 
{ 
    FragmentManager fragmentManager = getFragmentManager(); 
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
    fragmentTransaction.add(id, fragment); 
    fragmentTransaction.commit(); 
} 

Utilizzando un'operazione di menu voglio caricare Fragment_B in frameLayoutA e Fragment_C in frameLayoutB. L'operazione di menu è:

removeFragmentsInActivity(R.id.frameLayoutB,fragB); 
    addFragmentsInActivity(R.id.frameLayoutB,fragC); 
    if(!fragB.isAdded()){ 
      Log.e("check", "fragB already removed from frameLayoutB"); 
     removeFragmentsInActivity(R.id.frameLayoutB,fragB); 
     addFragmentsInActivity(R.id.frameLayoutA,fragB); 
    } 
    else{ 
     Log.e("check", "fragB already added"); 
    }  

    public void removeFragmentsInActivity(int id, Fragment fragment) 
    { 
     FragmentManager fragmentManager = getFragmentManager(); 
     FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
     fragmentTransaction.remove(fragment); 
     fragmentTransaction.commit(); 
    } 

Fragment_B non viene visualizzato in frameLayoutA. frameLayoutA mostra Fragment_A. Quando si fa nuovamente clic sul comando Menu, viene caricato il Fragment_B.

Debug Ho rilevato che dopo fragB.isAdded() restituisce true dopo l'operazione fragB.remove(). Durante la seconda operazione di menu fragB.isAdded() restituisce false e fragB.add() viene eseguito e FragmentB viene mostrato in frameLayoutA.

Capisco che commit è un'operazione asincrona. isAdded return true perché commit is async e remove operation non viene eseguito fino al momento in cui viene chiamato fragB.isAdded(). È vero?

Gentilmente suggerire la possibile soluzione o approccio per risolvere il problema.

saluti, vibhor

risposta

25

Sì la transazione si è impegnata in modo asincrono. Se si vuole fare in modo tutti trasactions hanno finito prima di eseguire isAdded, eseguire:

getFragmentManager().executePendingTransactions(); 

Dalla documentazione per executePendingTransactions():

Dopo un FragmentTransaction si impegna con FragmentTransaction.commit(), è prevista da eseguire in modo asincrono sul thread principale del processo. Se si desidera eseguire immediatamente tali operazioni in sospeso, è possibile chiamare questa funzione (solo dal thread principale) per farlo. Tieni presente che tutte le callback e altri comportamenti correlati verranno eseguiti all'interno di questa chiamata, quindi fai attenzione a da dove viene chiamato.

Quindi il codice dovrebbe essere simile:

removeFragmentsInActivity(R.id.frameLayoutB,fragB); 
addFragmentsInActivity(R.id.frameLayoutB,fragC); 
getFragmentManager().executePendingTransactions(); 
if(!fragB.isAdded()){ 
     Log.e("check", "fragB already removed from frameLayoutB"); 
    removeFragmentsInActivity(R.id.frameLayoutA,fragA); 
    addFragmentsInActivity(R.id.frameLayoutA,fragB); 
} 
else{ 
    Log.e("check", "fragB already added"); 
} 

nota fissa anche la rimozione del frammento A.

+0

Grazie per l'aiuto ... ha funzionato. – vibhor

0

forse il vostro può encapture Commition di FragmentTransaction come questo

private void commitFragmentTransaction(final FragmentTransaction ft, boolean allowStateLoss, boolean now) { 
    if (ft == null || ft.isEmpty()) { 
     return; 
    } 

    if (allowStateLoss) { 
     if (now) { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 
       ft.commitNowAllowingStateLoss(); 
      } else { 
       ft.commitAllowingStateLoss(); 
       mFragmentManager.executePendingTransactions(); 
      } 
     } else { 
      ft.commitAllowingStateLoss(); 
     } 
    } else { 
     if (now) { 
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 
       ft.commitNow(); 
      } else { 
       ft.commit(); 
       mFragmentManager.executePendingTransactions(); 
      } 
     } else { 
      ft.commit(); 
     } 
    } 
} 

commitNow () e viene aggiunto commitNowAllowingStateLoss() nel livello API 24

Chiamare commitNow è preferibile chiamare commit() seguito da executePendingTransactions() poiché quest'ultimo avrà l'effetto collaterale di tentare di impegnare tutte le transazioni attualmente in sospeso indipendentemente dal fatto che si tratti del comportamento desiderato.

Problemi correlati