2012-05-23 10 views
9

tengo una actividad con debajo diseñoFragment.isAdded devuelve verdadero después de fragmento retirado de un recipiente

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

En onCreate de actividad, me carga Fragment_A en frameLayoutA y Fragment_B en 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(); 
} 

Utilizando una operación de menú quiero cargar Fragment_B en frameLayoutA y Fragment_C en frameLayoutB. La operación de menú es:

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 no se muestra en frameLayoutA. frameLayoutA muestra Fragment_A. Cuando se hace clic nuevamente en la operación del Menú, se carga Fragment_B.

Depuración Encontré que después de fragB.isAdded() devuelve verdadero después de que se realiza la operación fragB.remove(). Durante la operación del segundo menú, fragB.isAdded() devuelve falso y fragB.add() se ejecuta y FragmentB se muestra en frameLayoutA.

Entiendo que la confirmación es una operación asíncrona. isAdded devuelve true porque commit es async y remove la confirmación de operación no se realiza hasta que se invoca fragB.isAdded(). ¿Es verdad?

Por favor, sugiera la posible solución o enfoque para resolver el problema.

Saludos, Vibhor

Respuesta

25

Si la transacción se confirma de forma asíncrona. Si desea asegurarse de que todos los trasactions han terminado antes de ejecutar isAdded, ejecute:

getFragmentManager().executePendingTransactions(); 

De la documentación para executePendingTransactions():

Después de un FragmentTransaction está comprometido con FragmentTransaction.commit(), que está previsto para ejecutarse de forma asincrónica en el hilo principal del proceso. Si desea ejecutar inmediatamente cualquiera de estas operaciones pendientes, puede llamar a esta función (solo desde el hilo principal) para hacerlo. Tenga en cuenta que todas las devoluciones de llamada y otros comportamientos relacionados se realizarán desde esta llamada, por lo tanto, sea teniendo cuidado de dónde se llama.

lo tanto, su código debería ser similar:

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 También se ha corregido la eliminación del fragmento A.

+0

Gracias por la ayuda ... funcionó. – vibhor

0

tal vez su encapture puede commition de FragmentTransaction como esto

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 () y commitNowAllowingStateLoss() se agrega en el nivel API 24

Llamar a commitNow es preferible a llamar a commit() seguido de executePendingTransactions() ya que este último tendrá el efecto secundario de intentar comprometer todas las transacciones actualmente pendientes, ya sea que se trate del comportamiento deseado o no.

Cuestiones relacionadas