Analizar los motivos de la superposición de fragmentos desde la perspectiva del código fuente
¿Por qué se superponen los Fragmentos?
Analice desde la perspectiva del código fuente, ¿por qué se produce la superposición cuando se reinicia la página? (Cuando se usa agregar para cargar Fragmento)
Sabemos que hay un método onSaveInstanceState() en Actividad. Cuando la aplicación entra en segundo plano, antes de que la pantalla gire, salta a la siguiente
, podemos guardar. póngalo en onRestoreInstanceState() o onCreate( ) para restaurar el progreso de la reproducción y otros estados.
El motivo de la superposición de Fragmentos está relacionado con el mecanismo de guardar el estado. La razón general es que el sistema nos ayuda a guardar el estado de Fragmento antes de reiniciar la página, pero al restaurar después de reiniciar, el estado visible de. la vista no se guarda para nosotros y el estado predeterminado de Fragment es el estado de visualización, por lo que se produce la superposición de Fragment.
Análisis: Echemos un vistazo al código fuente de FragmentActivity:
la clase pública FragmentActivity se extiende...{
final FragmentController mFragments = FragmentController.createController( new HostCallbacks());
protected void onCreate(@ Paquete anulable saveInstanceState) {
...omitido
if (savedInstanceState ! = null) {
...omitido
p>
Parcelable p = saveInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, nc ! = null ? nc.fragments : null);
} p>
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState( outState);
Parcelable p = mFragments.saveAllState( );
...omitido
}
}
En el código fuente anterior, puede ver que FragmentActivity es efectivamente. Guardamos el estado del Fragmento y lo restauramos después de reiniciar la página.
Entre ellos, mFragments es FragmentController, que es un controlador que controla indirectamente FragmentManagerImpl a través de FragmentHostCallback.
El código relevante es el siguiente:
clase pública FragmentController {
privado final FragmentHostCallbacklt;?mFragmentManager.restoreAllState(state, nonConfigList);
}
}
clase abstracta pública FragmentHostCallbacklt; Egt; extiende FragmentContainer {
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
}
Como se puede ver en el código anterior, FragmentHostCallback restaura FragmentController a través del control de objetos FragmentManagerImpl.
A continuación, echemos un vistazo a la funcionalidad real de FragmentManagerImpl:
clase final FragmentManagerImpl extiende FragmentManager {
Parcelable saveAllState() {<
...mBackStack = backStack;
Devolver fms;
}
void restaurarAllState(Estado parcelable, Listlt; Fragmentgt; nonConfig) {
// Restaurar código central
FragmentManagerState fms = (FragmentManagerState)state;
FragmentState fs = fms.mActive[i];
.. . Omitido
mInstance = Fragment.instantiate(context, mClassName, mArguments);
}
}
En este punto, entender el sistema El Fragmento guardado para nosotros termina siendo en realidad un FragmentState.
En este punto, pensemos en por qué se produce la superposición de fragmentos después de reiniciar la página.
De hecho, la respuesta ya es obvia. Según el análisis del código fuente anterior, encontraremos que no hay ningún campo de estado oculto en FragmentState.
El estado Oculto corresponde a mHidden en Fragmento, y el valor predeterminado es falso...
clase pública Fragmento...{
boolean mHidden;
p>
}
Creo que debes entender que al cargar un Fragmento agregando, el sistema restaurará el Fragmento con mHidden = false, es decir, el estado de visualización. Esto
Después de reiniciar la página, el fragmento de actividad se mostrará en el estado de visualización. Si no toma ninguna medida, se producirá una superposición de fragmentos.
¿Por qué cargar fragmentos usando add() provoca fragmentos superpuestos?
Sabemos que existen 2 métodos para cargar Fragment: reemplazar() y agregar(). Usar reemplazar para cargar un Fragmento no causará superposición, solo usar agregar puede causar superposición.
Usualmente usamos agregar, mostrar() y ocultar(), donde agregar y ocultar son para cambiar la vista del Fragmento al estado GONE y
reemplazar es destruir la vista del Fragmento;
Ver. Cuando se reinicia la página, todos los Fragmentos de agregar pasarán por el ciclo de vida y crearán vistas, mientras que los Fragmentos de reemplazo no superiores no pasarán por el ciclo de vida. Solo pasarán por el ciclo de vida del Fragmento en el. parte superior de la pila uno por uno y regresar
< La vista se crea cuando p>.Según el análisis del código fuente anterior, cuando se usa reemplazar para cargar un Fragmento, después de reiniciar la página, la vista Fragmento aún no se ha creado, por lo que mHidden no tiene sentido y no se producirá ninguna superposición ; p>
Cuando se usa Cuando se carga add, las vistas existen y se apilan juntas después de reiniciar la página
Cuando mHidden=false, todos los Fragmentos se mostrarán en el estado de presentación (es decir, VISIBLE), provocando que los fragmentos se superpongan.