Red de conocimientos turísticos - Información de alquiler - Analizar los motivos de la superposición de fragmentos desde la perspectiva del código fuente

Analizar los motivos de la superposición de fragmentos desde la perspectiva del código fuente

1. Se produjo un reinicio de la página (obligado a cerrar y reiniciar debido a la rotación de la pantalla, memoria insuficiente, etc.). 2. Utilice add() para cargar Fragmento;

¿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

Actividad, etc. Se llamará a este método. En este momento, el sistema nos ayudará a guardar un tipo de datos de paquete. Podemos guardar manualmente algunos datos según nuestras propias necesidades, como el progreso de la reproducción. Luego, si se reinicia la página

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

}

@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

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.