2012-08-17 14 views
18

En la documentación de Android para los cargadores que se encuentra en http://developer.android.com/guide/components/loaders.html se dice que una de las propiedades de los cargadores es que:cargador se reinicia el cambio de orientación

se vuelven a conectar automáticamente al cursor del último cargador al ser recreada después de un cambio de configuración. Por lo tanto, no necesitan volver a consultar sus datos.

El siguiente código no parece reflejar ese comportamiento, se crea un nuevo cargador y finaliza la consulta del ContentResolver, ¡luego giro la pantalla y el Loader se vuelve a crear!

public class ReportFragment extends Fragment implements LoaderCallbacks<Cursor> { 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     getLoaderManager().initLoader(1, null, this); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     View v = inflater.inflate(R.layout.fragment_report, container, false); 
     return v; 
    } 

    public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) { 
     Log.d("TEST", "Creating loader"); 
     return new CursorLoader(getActivity(), ResourcesContract.Reports.CONTENT_URI, null, null, null, null); 
    } 

    public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) { 
     Log.d("TEST", "Load finished"); 
    } 

    public void onLoaderReset(Loader<Cursor> arg0) { 

    } 

} 

Aquí está la salida de mi Logcat:

08-17 16:49:54.474: D/TEST(1833): Creating loader 
08-17 16:49:55.074: D/TEST(1833): Load finished 
*Here I rotate the screen* 
08-17 16:50:38.115: D/TEST(1833): Creating loader 
08-17 16:50:38.353: D/TEST(1833): Load finished 

Alguna idea de lo que estoy haciendo mal aquí?

EDIT:

Debo señalar que estoy construyendo a Android versión de Google API 8, y el uso de la biblioteca de soporte v4.

segundo EDIT:

Esto es muy probablemente debido a un error en la biblioteca de soporte, echar un vistazo a este envío de errores si desea más información:

http://code.google.com/p/android/issues/detail?id=20791&can=5&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

+1

Consulte esta publicación para obtener más información: http://www.androiddesignpatterns.com/2012/08/implementing-loaders.html –

+2

Además, debe llamar a 'getLoaderManager()' en 'onActivityCreated' ... su código actual arrojará una 'IllegalStateException' si la' Activity' todavía es 'null' cuando se crea el' Fragment' por primera vez. –

+1

@AlexLockwood, en su ejemplo (¡buen trabajo!) Está utilizando support-v4: 18.0.0. La versión actual es 23.0.1 y contiene este error. La última versión de trabajo que probé es 22.0.0. –

Respuesta

-2

onCreate () se llama durante el cambio de orientación de pantalla ya que la actividad se destruye y vuelve a crear.

A menos que esté cargando una gran cantidad de datos, no hace daño, pero puede intentar lo siguiente si lo desea (no lo he probado, pero en teoría creo que funcionaría).

Declara un booleano estático en la parte superior global de la clase. Yo creo también necesitará un cursor estático para hacer referencia

private static boolean dataDownloaded = false; 
private static Cursor oldCursor; 

Luego, el onLoadFinished establece dataDownloaded = true

Anulación onSaveInstanceState para guardar el valor booleano

@Override 
protected void onSaveInstanceState(Bundle outSave) { 
    outSave.putBoolen("datadownloaded", dataDownloaded); 
    oldCursor = adapter.swapCursor(null); 
} 

y onCreate añadir el siguiente

if (savedInstanceState != null) { 
    this.dataDownloaded = savedInstanceState.getBoolean("datadownloaded", false); 
} 

ajustar sus onCreateLoader

public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
    CursorLoader cursorLoader; 
    if (dataDownloaded) { 
     cursorLoader = new CursorLoader(getActivity(), 
      null, projection, null, null, null); 
     cursorLoader.deliverResult(oldCursor); 
    } else { 
     CursorLoader cursorLoader = new CursorLoader(getActivity(), 
      URI_PATH, projection, null, null, null); 
    } 

    return cursorLoader; 
} 
+0

¿No haría esto una consulta al ContentResolver de cualquier manera (no importa si dataDownloaded es verdadero o falso, aún se crea un CursorLoader nuevo)? De todos modos, creo que esto está sucediendo debido a un error con las bibliotecas de soporte, consulte esta publicación para obtener más información: https://groups.google.com/forum/?fromgroups#!topic/android-developers/DbKL6PVyhLI%5B1- 25% 5D –

+0

Lo ajusté ... se suponía que era "nulo" para la ruta del URI si los datos ya se habían descargado – ainesophaur

+0

Tiene sentido ahora. Bueno, esta es una solución por lo que puedo ver, así que lo marcaré como uno solo. Gracias por tu respuesta. –

-1

Simplemente puede comprobar para ver si el cargador ya existe onCreate. Entonces puedes iniciar o reiniciar.

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    if (getLoaderManager().getLoader(LOADER_ID) == null) { 
     getLoaderManager().initLoader(LOADER_ID, null, this); 
    } else { 
     getLoaderManager().restartLoader(LOADER_ID); 
    } 
} 

Normalmente, usted pasa una identificación a su cargador para que pueda consultarlo más tarde a través del gestor de carga.

Espero que esto ayude!

+0

Hola Nelson, esto reiniciaría el cargador si ya existe uno, lo cual desafía su propósito.Incluso si cambiaras las dos instrucciones (init y restart), ¡daría como resultado el mismo comportamiento que llamar a initLoader en primer lugar! –

+2

getLoaderManager(). RestartLoader (LOADER_ID); hace exactamente lo mismo que la declaración completa "if() {} else {}" porque restartLoader hace exactamente lo mismo si el Loader aún no existe. –

0

Hasta ahora he encontrado que la retención del fragmento Fragment.setRetainInstance(true) impide la recreación del cargador en el cambio de orientación mediante la biblioteca de soporte. Los últimos resultados de la cargadora se entregan fácilmente en onLoadFinished(). Funciona al menos cuando la actividad administra un fragmento individual y el fragmento se agrega a la actividad usando FragmentTransaction.

0

Aunque esta es una pregunta un poco vieja, me gustaría poner mi punto de vista aquí.

No hay necesidad de almacenar información adicional en onSaveInstanceState

El marco vuelva a conectar automáticamente a la última cursor del cargador al ser recreada después de un cambio de configuración. Por lo tanto, no necesitan volver a consultar sus datos.

Esto significa que en la función onCreate necesita llamar loaderManager sólo si el savedInstanceState es nulo

Ex:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    if(savedInstanceState == null) { 
     getLoaderManager().initLoader(1, null, this); 
    } 
} 
1

Aunque esta es una vieja pregunta, he estado experimentando el mismo problema que el OP. Utilizando un cargador, necesito que se reinicie cuando navegue a una nueva actividad, y luego de vuelta. Pero al mismo tiempo, no quiero que el cargador se reinicie cuando gire la pantalla del teléfono.

Lo que encontré es que es posible lograr esto en onRestart(), si reinicia el cargador ANTES de llamar a su súper.

public class MainActivity extends AppCompatActivity implements 
LoaderManager.LoaderCallbacks<Cursor> { 

    ... 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     ... 

     //Initialize the loader. 
     getSupportLoaderManager().initLoader(0, null, this); 
    } 

    @Override 
    protected void onRestart() { 
     //Restart the loader before calling the super. 
     getSupportLoaderManager().restartLoader(LOADER_ID, null, this); 

     super.onRestart(); 
    } 

    ... 

} 
+0

+1 Gracias :) Esto me ayudó con mi problema :) Estoy usando AdapterViewFlipper y siguiendo sus consejos para administrar mi cargador, la aleta ya no se ve afectada por la rotación de la pantalla :) –

0

En mi opinión usted no entendió lo que dice la documentación. La documentación dice que no necesitan volver a consultar sus datos, y no lo está haciendo.

Intente iniciar/insertar un punto de interrupción en su método ContentProvider#query()! La consulta se invocará solo al inicio de la actividad y no después del cambio de orientación.

Pero esto no es cierto para el método LoaderCallbacks#onCreateLoader(). Se llamará después de cada cambio de orientación, pero esto no significa volver a consultar, simplemente llama al método para que pueda cambiar el CursorLoader si lo desea.

Cuestiones relacionadas