tutorial - navegar entre fragments android studio
onCreate() y onCreateView() invocan mucho más de lo necesario(Fragmentos) (6)
¿Alguien puede explicar por qué se onCreate()
y onCreateView()
tantas veces que se incrementa con cada orientación?
Aquí hay una aplicación muy simple que consiste en una Activity
compuesta de dos Fragments
. El segundo Fragment
carga dinámicamente . Si defines estos dos Fragments
en main.xml
no existiría tal comportamiento.
Aquí está main.xml
:
<fragment class="ets.saeref.Left"
android:id="@+id/left_frag"
android:layout_weight="70"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<FrameLayout android:id="@+id/right_frag"
android:layout_weight="30"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Aquí está el fragmento izquierdo:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent" android:background="#000000">
<Button android:text="Landscape" android:id="@+id/button1"
android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
</LinearLayout>
Aquí está el fragmento correcto:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent" android:background="#ffffff">
<Button android:text="Landscape" android:id="@+id/button1"
android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
</LinearLayout>
Left.class:
public class Left extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("Left", "onCreate()");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.i("Left", "onCreateView()");
return inflater.inflate(R.layout.left, container, false);
}
}
Right.class:
public class Right extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("Right", "onCreate()");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.i("Right", "onCreateView()");
return inflater.inflate(R.layout.right, container, false);
}
}
Clase principal:
public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Fragment fg = new Right();
getFragmentManager().beginTransaction().add(R.id.right_frag, fg)
.commit();
Log.i("Main", "onCreate()");
}
}
Inicie sesión después de varios cambios de orientación:
08-28 21:47:38.220: INFO/Main(1099): onCreate()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:38.220: INFO/Right(1099): onCreate()
08-28 21:47:38.220: INFO/Right(1099): onCreateView()
08-28 21:47:41.110: INFO/ActivityManager(142): Config changed: {1.0 0mcc0mnc en_US sw800dp w1280dp h752dp xlrg land finger -keyb/v/h -nav/h s.162}
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.140: INFO/Right(1099): onCreate()
08-28 21:47:41.170: INFO/Left(1099): onCreate()
08-28 21:47:41.170: INFO/Left(1099): onCreateView()
08-28 21:47:41.170: INFO/Main(1099): onCreate()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.170: INFO/Right(1099): onCreateView()
08-28 21:47:41.190: INFO/Right(1099): onCreate()
08-28 21:47:41.190: INFO/Right(1099): onCreateView()
08-28 21:47:45.070: INFO/ActivityManager(142): Config changed: {1.0 0mcc0mnc en_US sw800dp w800dp h1232dp xlrg port finger -keyb/v/h -nav/h s.163}
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.120: INFO/Right(1099): onCreate()
08-28 21:47:45.130: INFO/Left(1099): onCreate()
08-28 21:47:45.130: INFO/Left(1099): onCreateView()
08-28 21:47:45.130: INFO/Main(1099): onCreate()
08-28 21:47:45.130: INFO/Right(1099): onCreateView()
08-28 21:47:45.130: INFO/Right(1099): onCreateView()
08-28 21:47:45.130: INFO/Right(1099): onCreateView()
08-28 21:47:45.140: INFO/Right(1099): onCreateView()
08-28 21:47:45.140: INFO/Right(1099): onCreateView()
08-28 21:47:45.140: INFO/Right(1099): onCreate()
08-28 21:47:45.140: INFO/Right(1099): onCreateView()
¡Parece que tienes tantos fragmentos allí! Si define un fragmento en un archivo xml, ¡ no podrá volver a definir "it" en su código! Hay dos formas de definir los fragmentos: dynamiclly (en su código) y estáticamente (en su xml)! Eche un vistazo aquí: http://marakana.com/s/post/1250/android_fragments_tutorial
Es realmente un buen tutorial.
No puedo señalar la documentación que explica esto, pero la solución es solo crear y agregar el fragmento cuando la actividad se carga por primera vez, como esta:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (savedInstanceState == null) {
Fragment fg = new Right();
getFragmentManager().beginTransaction().add(R.id.right_frag, fg)
.commit();
}
Log.i("Main", "onCreate()");
}
Sí, esto está muy mal documentado. La explicación es que cuando la Activity
se restored
"auto-mágicamente" los Fragments
que se agregaron en ella, por lo que adding
otro Fragment
en tu Activity
básicamente agregará otro Fragment
nuevo en la parte superior de los Fragment/s
anteriores que en realidad están restored
por Android
.
Este comportamiento definitivamente es intencionado, y el enfoque sugerido por @Joris Wit es el correcto.
También esto es muy útil cuando lo piensas, porque digamos que tienes una pila de Fragments
agregados uno encima del otro, y puedes volver a ellos usando la tecla back
. En el caso de una rotación, si Android
no restaura la copia de respaldo de los Fragments
, los perderá a todos, o tendrá que implementar algún mecanismo para hacer un seguimiento de su stack
Fragment
.
Si no usa diseños diferentes para diferentes orientaciones, creo que debería usar android:configChanges="orientation"
en su manifiesto. http://developer.android.com/guide/topics/manifest/activity-element.html#config
Un cambio de orientación hace que el sistema pase por el proceso de guardar estado de instancia, pausar, detener, destruir y luego crear una nueva instancia de la actividad con el estado guardado. Esta es la razón por la que hay tantas llamadas onCreate y onCreateView.
No creo que la if (savedInstanceState == null)
en el método onCreate
sea una buena idea; el mecanismo de ahorro de estado no funcionará correctamente ...
la clase principal debería extender FragmentActivity y no Activity.
también busca Ciclo de vida de la actividad en el documento de Android