2012-04-25 11 views
7

Estoy enfrentando un problema al usar AsyncTaskLoader y la orientación de la pantalla cambia. Déjame darte un contexto sobre cómo está estructurada mi aplicación: tengo una aplicación muy simple que obtiene resultados de una url y la muestra. La aplicación consta de un FragmentActivity y tres Fragments. Mis tres fragmentos son los siguientes:No se está llamando al cargador cuando cambia la orientación de la pantalla

  • El primer fragmento es un texto de edición y un botón para enviar la entrada.
  • El segundo fragmento muestra un spinner de carga
  • El tercer fragmento reemplaza el fragmento de carga cuando se obtienen los datos para mostrar los resultados.

El AsyncTaskLoader se utiliza para cargar datos de un proveedor de contenido (si se trata de caché) o desde la red.

¡Todo funciona bien hasta que cambie la pantalla original! Miré el resultado de LoaderManager.enableDebugLogging(true) y parece que el origen del problema es que LoaderCallbacks.onLoadFinished no se llama en mi actividad.

Aquí es una pieza del código que pone en marcha el cargador:

/* This function is defined in the "first" fragment in an interface and 
* implemented in the activity */ 
@Override 
public void onFormSubmission(String word) {      

    showLoadingFragment(); 

    if (mWord == null || mWord.equals(word)) { 
     getSupportLoaderManager().initLoader(0, word, this); 
    } else { 
     getSupportLoaderManager().restartLoader(0, word, this); 
    } 

    // Store the word 
    mWord = word; 
} 

El código que muestra el resultado:

@Override 
public void onLoadFinished(Loader<Bundle> loader, Bundle data) { 
    // Validation and other stuff 

     ResultFragment fragment = new ResultFragment(); 

     // Add the fragment to the 'result_fragment_container' FrameLayout 
     getSupportFragmentManager() 
      .beginTransaction() 
      .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) 
      .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) 
      // Replace loading fragment with the result 
      .replace(R.id.result_fragment_container, fragment) 
      .commitAllowingStateLoss(); 
} 

enfoques que intentó sin éxito:

  • Ajuste setRetaininstance(true) en fragmentos.
  • Configuración android:configChanges="orientation|keyboardHidden|keyboard" en el manifiesto.

Me quedo sin ideas, por lo que cualquier ayuda sería apreciada.

+0

Debe evitar confirmar 'FragmentTransaction's inside' onLoadFinished() '... es malo para la experiencia del usuario. Consulte mi [** publicación de blog **] (http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html) sobre este tema para obtener más información. –

Respuesta

1

Debe poner getSupportLoaderManager().initLoader(0, null, this); en el método onActivityCreated. El initLoader creará o volver a conectar con un cargador si ya existe

1

Hola que puedo sugerir posibles soluciones: 2

1) Desde su pregunta no estoy del todo seguro de lo que procese su rendimiento que nunca está llamando OnLoadFinished() en AsyncTask. Asumiré que es una llamada al DB Async o una llamada al servidor web, etc.

Independientemente de que onLoadFinished() probablemente no se llame porque su actividad se destruye en la rotación. debe guardar el estado que actualizó antes de la rotación y onDestroy() se llama

Puede intentar mantener un indicador de estado de variable de clase. Esto se establece en su tarea de "actualización" Async que indica si su tarea Async aún se está ejecutando, es decir, "actualizando" o no.

Así:

  • bUpdating = true cuando su tarea de actualización async comienza.Es decir, dentro de onPreExecute()
  • bUpdating = false cuando está terminado. Es decir, dentro onPostExecute()

Luego, cuando onDestroy() se llama (llama siempre antes de la rotación de la pantalla) se puede comprobar bUpdating. IFTRUE entonces se podría guardar todos los datos que aparecen en pantalla, que se han guardado en la tarea Async, a SharePreferences

Dentro onResume() revisar sus SharePreferences variables específicas y si es que existen entonces KickOff la actualización Async nuevo.

Así que en breve esta voluntad:

  • guardar los detalles de SharedPreferencesANTES rotación de la pantalla - onDestroy() - si booleano dice tarea en ejecución asíncrono.
  • onResume()DESPUÉS rotación de pantalla, marque SharedPreferences y guarde los detalles a través de Async.
  • Después de esto, debe tener la garantía de que se llama al método onLoadFinished().

Probablemente haya una manera más confiable también de comprobar la rotación de la pantalla, no he hecho mucho con ella.

2) Por supuesto, otra alternativa es bloquear la rotación de la pantalla completamente en su Actividad particular (porque realmente, ¿NECESITA rotación en esa pantalla?).

Tengo una aplicación que graba video en segundo plano y carga segmentos de 10 segundos. Causaba grandes dolores de cabeza con la rotación de la pantalla y mis tareas Async, así que bloqueé la rotación por completo, ya que era completamente innecesaria. Aquí está el código para el archivo AndroidManifest.xml para bloquear la orientación de la pantalla como Retrato:

 <activity 
     android:name="com.blah.YourActivity" 
     android:label="Register" 
     android:screenOrientation="portrait"> 
    </activity> 

espero que pueda ayudar a salir

Editar: También, podría ser mejor maneras más categóricos para saber que la pantalla está girando:

es decir, este tipo de código:

public void onConfigurationChanged(Configuration newConfig) { 
    super.onConfigurationChanged(newConfig); 

    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { 
     Log.e(TAG, "ORIENTATION_LANDSCAPE"); 
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { 
     Log.e(TAG, "ORIENTATION_PORTRAIT"); 
    } 
} 

Ejemplo tomado de esta post

puede poner su SharePreferences guardar allí. pero onResume() seguirá utilizándose para recuperar sus datos.

También un link to SharePreferences en caso que usted no ha utilizado antes

Edit2 !: Una otra cosa. Acabo de volver a leer tu pregunta, y mencionas "Loader" por alguna razón que tuve en mi cabeza esto fue guardar datos, no cargarlos. ¿Has intentado simplemente volver a llamar al AsyncTaskLoader() cuando se llama onResume()?Si no guarda, puede ignorar todo lo que dije acerca de conservar sus datos en SharePreferences porque puede iniciar nuevamente la tarea Async de carga en onResume() (que se ejecuta después de la rotación)

Cuestiones relacionadas