No se puede pausar la actividad, la vista de contenido aún no se ha creado

Tomé el proyecto de muestra de EU4You demostrado en la Guía del codificador ocupado de Android Development 4.2 (cortesía de Mark Murphy aka commonsware aquí en StackOverflow). Puede ser más fácil seguir junto con este proyecto de ejemplo, pero intentaré publicar porciones relevantes de código en la pregunta. También es necesario importar el proyecto ActionBarSherlock . También necesitará establecer el compilador de Java en 1.6 (para permitir la anotación @Override).

NOTA: He cambiado el min-sdk a 8 (2.3, Froyo) y el target-sdk a 16 (4.1, Ice Cream Sandwich).

Nota: He cambiado los countries framelayout id a left_pane y los details framelayout id a right_pane .

Archivo de diseño principal (layout-large-land):

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <FrameLayout android:id="@+id/left_pane" android:layout_weight="30" android:layout_width="0px" android:layout_height="fill_parent" /> <FrameLayout android:id="@+id/right_pane" android:layout_weight="70" android:layout_width="0px" android:layout_height="fill_parent" /> </LinearLayout> 

Archivo de diseño principal:

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/left_pane" android:layout_width="fill_parent" android:layout_height="fill_parent" /> 

La versión original de la aplicación de ejemplo tiene dos actividades (SherlockFragmentActivities para ser exactas).

  1. EU4You – Carga el diseño adecuado (predeterminado o horizontal). Si es predeterminado, carga una lista de países en un SherlockListFragment. Si es grande, carga la lista y un fragmento de detalles para mostrar el país seleccionado.
  2. DetailsActivity – Carga el país seleccionado a través del DetailsFragment cuando no se utiliza el diseño de gran tamaño horizontal.

Si hace clic en un país del fragmento de lista, EU4You (la principal actividad de alojamiento) comprueba la existencia y visibilidad del DetailsFragment. Si existe, carga el sitio web del país dentro de ese fragmento. De lo contrario, se desencadena el DetailsActivity, que a continuación, se encarga de agregar el DetailsFragment (que luego carga el sitio web para el país dado).

Esto funciona bien, como una aplicación típica que admite múltiples diseños de pantalla en tabletas y teléfonos.

Mi problema es que quiero quitar el DetailsActivity y pegarse a una sola actividad. Quiero intercambiar (reemplazar) el fragmento de lista con el fragmento de detalles siempre que no esté en el diseño de paisaje grande (en otras palabras, estoy en un diseño de retrato en una tableta o en un auricular en cualquier orientación). Así que lo que he hecho, se cambia lo siguiente en el EU4You SherlockFragmentActivity:

Original (con ligera modificación de nombres en los nombres de framelayout mencionados en la nota más arriba … countries es left_pane, los detalles son right_pane):

 @Override public void onCountrySelected(Country c) { String url=getString(c.url); if (details != null && details.isVisible()) { details.loadUrl(url); } else { Intent i=new Intent(this, DetailsActivity.class); i.putExtra(DetailsActivity.EXTRA_URL, url); startActivity(i); } } 

Mi versión de una sola actividad modificada:

 @Override public void onCountrySelected(Country c) { String url=getString(c.url); if (details != null && details.isVisible()) { details.loadUrl(url); } else { details = new DetailsFragment(); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.replace(R.id.left_pane, details); ft.addToBackStack(null); ft.commit(); getSupportFragmentManager().executePendingTransactions(); details.loadUrl(url); } } 

Esto funciona como se esperaba. Hago clic en un sitio web de la lista (en el modo retrato en una tableta o en un teléfono en cualquier orientación) y los detalles se muestran en el fragmento de detalles, que sustituye al fragmento de lista de sitios web. Sin embargo, si a continuación, haga clic en el botón de inicio en el dispositivo, mientras que los detalles del país se muestran, me sale un error de cierre de la fuerza, con los siguientes datos de logcat (sólo con el diseño por defecto con el único left_pane framelayout … I don ' T tiene este problema en la orientación horizontal en tabletas, cuando hay un left_pane y right_pane):

 11-16 15:04:33.525: E/AndroidRuntime(688): FATAL EXCEPTION: main 11-16 15:04:33.525: E/AndroidRuntime(688): java.lang.RuntimeException: Unable to pause activity {com.commonsware.android.eu4you/com.commonsware.android.eu4you.EU4You}: java.lang.IllegalStateException: Content view not yet created 11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3348) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3305) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3288) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.access$2500(ActivityThread.java:125) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2040) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.os.Handler.dispatchMessage(Handler.java:99) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.os.Looper.loop(Looper.java:123) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.main(ActivityThread.java:4627) 11-16 15:04:33.525: E/AndroidRuntime(688): at java.lang.reflect.Method.invokeNative(Native Method) 11-16 15:04:33.525: E/AndroidRuntime(688): at java.lang.reflect.Method.invoke(Method.java:521) 11-16 15:04:33.525: E/AndroidRuntime(688): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 11-16 15:04:33.525: E/AndroidRuntime(688): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 11-16 15:04:33.525: E/AndroidRuntime(688): at dalvik.system.NativeStart.main(Native Method) 11-16 15:04:33.525: E/AndroidRuntime(688): Caused by: java.lang.IllegalStateException: Content view not yet created 11-16 15:04:33.525: E/AndroidRuntime(688): at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.support.v4.app.ListFragment.getListView(ListFragment.java:222) 11-16 15:04:33.525: E/AndroidRuntime(688): at com.commonsware.android.eu4you.CountriesFragment.onSaveInstanceState(CountriesFragment.java:64) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.support.v4.app.FragmentManagerImpl.saveFragmentBasicState(FragmentManager.java:1574) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.support.v4.app.FragmentManagerImpl.saveAllState(FragmentManager.java:1644) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.support.v4.app.FragmentActivity.onSaveInstanceState(FragmentActivity.java:499) 11-16 15:04:33.525: E/AndroidRuntime(688): at com.actionbarsherlock.app.SherlockFragmentActivity.onSaveInstanceState(SherlockFragmentActivity.java:127) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.Activity.performSaveInstanceState(Activity.java:1036) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1180) 11-16 15:04:33.525: E/AndroidRuntime(688): at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3330) 11-16 15:04:33.525: E/AndroidRuntime(688): ... 12 more 

Puedo parar este error de ocurrir, si quito la línea siguiente del código arriba:

 ft.addToBackStack(null); 

Necesito poder agregar la transacción de reemplazo a la backstack, por lo que no puedo eliminar esta línea (esta aplicación de ejemplo es la base para mi aplicación real que tiene más cosas, pero lo usé para simplificar mi problema).

Así que dos preguntas:

  1. ¿Por qué está pasando esto?
  2. ¿Cómo puedo solucionarlo (tal vez otro enfoque)?

Una cosa a tener en cuenta es que en mi aplicación real, esta lógica debe caer dentro de las pestañas en una barra de acción (ActionBarSherlock ya que debo apoyar de nuevo a la versión 2.3 (Froyo)).


ACTUALIZACIÓN (2012-Nov-22 13:27 EST)

He publicado un proyecto de ejemplo en GitHub . Soy nuevo en el desarrollo de Eclipse y Android, así que puede que no haya incluido todo lo que necesitaba (el espacio de trabajo no estaba incluido y no creo que el proyecto de ActionBarSherlock esté incluido … tendría que ser importado (se puede encontrar aquí ) ).

No puedo comentar sobre su accidente específico, ya que no he visto ese error, aparte de suponer que está atado a replace() lugar de usar attach() / detach() (sólo una suposición).

Sin embargo, getSupportFragmentManager().executePendingTransactions(); Para mí es un olor de código. Mi conjetura es que usted está haciendo esto para el beneficio de details.loadUrl(url); . En su lugar, agregue un miembro de datos en DetailsFragment , algo como urlToBeApplied y loadUrl() almacenar el valor allí si WebView no existe todavía. A continuación, puede aplicar la URL en onCreateView() . Si esto ayudará con respecto a su accidente, no puedo decir.

Es posible que desee considerar publicar un proyecto de muestra completo que demuestre el problema, ya que cuenta con personas que reconocen el mensaje de error.


ACTUALIZAR

Basándome en la aplicación de ejemplo, pude diagnosticar mejor el problema.

Content view not yet created , en un ListFragment , significará que estamos tratando de llamar a getListView() para un fragmento que todavía no ha pasado por onCreateView() o ha pasado por onDestroyView() . Esto generalmente indica un problema de tiempo.

En este caso, como resulta, el trabajo que se estrellaba era superfluo, de todos modos. onSaveInstanceState() intenta mantenerse en la posición del ítem marcado, por lo que podemos volver a comprobarlo más tarde (por ejemplo, después de un cambio de configuración). Sin embargo, ni siquiera necesitamos estar en modo de comprobación en primer lugar cuando estamos en pantallas normal . El modo seleccionado es para el estado activated , lo cual es relevante cuando la lista y los detalles están lado a lado, pero es irrelevante cuando no lo son. Por lo tanto, la solución es simplemente no molestarse con la lógica onSaveInstanceState() si no estamos necesitando una selección persistente … que podemos obtener fácilmente llamando a isPersistentSelection() en nuestro listener .

Por el bien de la argumentación, sin embargo, vamos a fingir que teníamos que hacer este trabajo. En ese caso, tenemos un par de opciones. El más simple probablemente es anular onDestroyView() y almacenar en caché la posición del ítem marcado, usando eso en onSaveInstanceState() si getListView() devuelve null .

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.