studio rotación rotacion reinicie que porque pantalla orientación orientacion movil manejando horizontal girar gira fijar evitar detectar como celular cambio activity android android-asynctask android-fragments android-viewpager

android - rotación - ASyncTask, fragmentos ocultos, instancias de retención y cambios de orientación de pantalla



porque no gira la pantalla de mi celular (1)

Hay algunos problemas aquí que estás experimentando (creo).

En primer lugar, la razón por la que se bloquean las devoluciones de llamada se debe a que están asociadas a una Activity que ya no existe después de una orientación de pantalla y / o Activity . Si usa onAttach() para adjuntar una devolución de llamada a su fragmento, debe usar onDetach() para desconectar esa devolución de llamada cuando el fragmento se elimine de la Activity . Luego, cada vez que llame a la devolución de llamada, verifique que no haya nulo para que no envíe datos a un objeto muerto.

Básicamente, la lógica que intentas usar aquí es:

  1. Actividad de inicio

  2. Verifica si tu Fragmento existe. Si es así, cógelo. De lo contrario, créelo.

  3. Recupere los datos si existen. Si no, espera la devolución de llamada.

Debido a la naturaleza de las devoluciones de llamadas (dependiendo de su implementación), no recibirá datos hasta que se desate el evento. Sin embargo, si la actividad se ha ido y el evento ya se ha activado, la devolución de llamada no se ejecutará. Por lo tanto, debe recuperar los datos manualmente. Cuando se usa setRetainInstance() , es útil pensarlo como esta entidad separada de su actividad. Existirá siempre y cuando no muestres la Activity actual o empujes una nueva Activity . Sin embargo, su Activity actual se destruirá al cambiar la orientación de la pantalla, mientras que el Fragment no lo hará. Como tal, el Fragment no debe confiar en la existencia de la Activity .

Una solución mucho más elegante al problema que quizás desee observar es la implementación de la API del cargador de Android. Los cargadores son herramientas prácticas que maneja el sistema y funcionan de forma similar, pero están más en sintonía con la recuperación asíncrona de datos. Funcionan efectivamente de la misma manera. Simplemente inicie su cargador y el sistema con crear uno si no existe o reutilizar uno que ya exista. Permanecerá en el sistema por el LoaderManager luego de los cambios de configuración.

EDITAR:

Para responder a su edición, supongo que explicaré lo que está sucediendo. Es intrincado, así que solo dime si algo necesita aclaración.

Los fragmentos técnicamente no son parte de su Activity actualmente en ejecución. Cuando crea una instancia del Fragmento, debe llamar a beginTransation() y commit() en el FragmentManager. FragmentManager es un singleton que existe dentro del ámbito de su aplicación. FragmentManager se aferra a la instancia del Fragment por ti. El FragmentManager luego asocia el Fragmento a tu Actividad (mira en onAttach() ). El Fragmento entonces existe dentro del FragmentManager, por lo que nunca tendrá que mantener una referencia en su aplicación. Puede llamar a findFragmentByTag/Id() para recuperarlo.

En circunstancias normales, cuando se destruye tu actividad, el FragmentManager separará la instancia de tu Fragmento (mira onDetach() ) y simplemente lo dejará ir. La recogida de basura de Java detectará que no existe ninguna referencia a su Fragmento y lo limpiará.

Cuando llama a setRetainInstace() , le está diciendo al FragmentManager que se setRetainInstace() a él. Por lo tanto, cuando su Actividad se destruya en un cambio de configuración, FragmentManager se aferrará a la referencia de su Fragmento. Por lo tanto, cuando se reconstruye tu actividad, puedes llamar a findFragmentByTag/Id() para recuperar la última instancia. Siempre que no mantenga ningún contexto de la última actividad, no debería haber ningún problema.

Tradicionalmente, uno lo usaría para mantener referencias a datos de larga data (como lo es usted) o para mantener abiertos los conectores de conexión para que un teléfono no lo elimine.

Tu ViewPager no tiene nada que ver con esto. La forma en que recupera los Fragmentos depende completamente de cómo implemente ese Adaptador al que está conectado. Por lo general, los Fragmentos retenidos no tienen Vistas porque las Vistas contienen datos de contexto de la Actividad en la que se crearon. Básicamente, lo único que desea es convertirlo en un depósito de datos para retener los datos de las Vistas que se extraen cuando están siendo inflado

Mi configuración es la siguiente.

Tengo un FragmentPagerAdapter llamado desde mi Actividad que carga dos fragmentos. Esto está configurado en onCreate.

En onResume llamo a ASyncTask que carga datos de una base de datos, y luego llama a una devolución de llamada en mi actividad onLoadComplete a través de un oyente de carga de datos.

@Override public void onLoadComplete(JSONArray data) { // TODO Auto-generated method stub LocalFragment fragmentB = (LocalFragment)getSupportFragmentManager().findFragmentByTag(ListTag); fragmentB.setList(data); LMapFragment fragmentA = (LMapFragment)getSupportFragmentManager().findFragmentByTag(MapTag); GoogleMap our_map = fragmentA.getMap(); fragmentA.plotP(myLocation,data); }

Los fragmentos son inicializados por el buscapersonas, y dentro de cada código de fragmentos establezco la etiqueta respectiva, por ejemplo, en LocalFragment

@Override public void onAttach(Activity activity) { // TODO Auto-generated method stub super.onAttach(activity); String myTag = getTag(); ((PagerTest) activity).setListTag(myTag); Log.d("what",myTag); }

Esto me permite acceder al fragmento, llamar a una función dentro de él que rellena una lista o rellena un mapa. Funciona.

Lo que intento hacer ahora es dar cuenta de los cambios de orientación de la pantalla. Si mientras ASyncTask se está ejecutando, la orientación cambia, la aplicación se bloquea.

Como se sugiere aquí: Fragmentos ocultos He intentado implementar un fragmento oculto que guarda el estado de mi ASyncTask. Entonces, lo que he hecho es configurarlo así en onResume de mi Actividad llamo una función

static LoadDataFromURL the_data = null; static JSONArray pub_data = null; private static final String TAG = "RetainFragment"; public RetainFragment() {} public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) { RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG); if (fragment == null) { fragment = new RetainFragment(); fm.beginTransaction().add(fragment, TAG).commit(); // add this } return fragment; }

que esencialmente salva mis datos.

Básicamente, lo que esto significa es que si giro mi pantalla, no vuelvo a llamar a mi ASyncTask ... la pantalla simplemente gira ... funciona perfectamente.

Sin embargo, si vuelvo al menú principal y vuelvo a hacer clic en la actividad, la pantalla vuelve a estar en blanco (pero no se cuelga). Según entiendo, los datos se conservan como un objeto en el fragmento, pero al volver a cargar la actividad, los datos deben volver a configurarse. Es necesario llamar al IE onLoadComplete para rellenar la lista / mapa.

Así que llegué a la conclusión de que si inicialmente después de que ASyncTask finalice, guardo los datos devueltos en mi fragmento oculto onRetainInstance, entonces simplemente podría llamar a OnLoadComplete y pasarlo.

El problema es que, aparentemente, en esta situación el fragmento aún no se ha invocado, por lo que las etiquetas son nulas, y al invocar las devoluciones de llamada en onLoadComplete, la aplicación se bloquea.

He estado golpeando mi cabeza sobre esto por años.

Mi ASyncTask está en una clase separada: LoadDataFromURL Lo que quiero lograr es lo siguiente: un fragmentoviewpager mediante el cual en la pantalla se rota la ASyncTask se retiene en rotar / adjuntar a la nueva actividad, y si se ha completado antes no se debe volver a ejecutar ..

¿Alguien podría aconsejar?

Muchas gracias

EDITAR

Después de haber cambiado las variables en mi fragmento secreto a las variables públicas, aparentemente todo se ha unido ... PERO porque no estoy 100% seguro de cómo y cuándo se llaman las cosas, no entiendo completamente POR QUÉ funciona.

Entonces ... invoco findOrCreateRetainFragment y crea un nuevo fragmento ''secreto'' o devuelve la instancia actual.

Si devuelve una instancia actual, no vuelvo a llamar a mi tarea asíncrona. Si no es así, llamo a mi asynctask y cargo los datos.

Con esta configuración, cuando cargo la actividad y giro la pantalla, gira como un woop esperado.

Ahora, cuando vuelvo al menú principal y luego hago clic en la actividad nuevamente, llama a la tarea asíncrona.

Según tengo entendido, al rotar la tarea asincrónica no se vuelve a llamar, y el visor está de alguna manera guardando los fragmentos.

Por otro lado, cuando vuelvo, mi actividad se destruye, como es mi fragmento secreto, y como tal cuando vuelvo a hacer clic en él carga los datos. Esto es esencialmente lo que quiero ...

¿Lo he entendido bien?

Gracias