studio oncreateloader loadermanager getloadermanager example dinamico android android-loadermanager android-cursorloader

android - oncreateloader - loadermanager



¿Cómo actualiza CursorLoader automáticamente la vista incluso si la aplicación está inactiva? (3)

Bueno, creo que puedes reiniciar el cargador en ciertos eventos. Por ejemplo, en mi caso tengo una actividad de TODOs. Al hacer clic en la opción ''agregar'', se inicia una nueva actividad que tiene vista para alimentar el nuevo TODO.

Estoy usando el siguiente código en la actividad de los padres enActivityResult ()

getLoaderManager().restartLoader(0, null, this);

Funciona bien para mí. Por favor, comparta si hay algún mejor enfoque.

He estado trabajando en una pequeña aplicación de lista de tareas pendientes. Utilicé CursorLoader para actualizar ToDolistview desde un proveedor de contenido. Tengo una función escrita en onNewItemAdded() , que se llama cuando el usuario ingresa un nuevo elemento en la vista de texto y hace clic en ingresar. Consulte a continuación:

public void onNewItemAdded(String newItem) { ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(ToDoContentProvider.KEY_TASK, newItem); cr.insert(ToDoContentProvider.CONTENT_URI, values); // getLoaderManager().restartLoader(0, null, this); // commented for the sake of testing } @Override protected void onResume() { super.onResume(); //getLoaderManager().restartLoader(0, null, this); // commented for the sake of testing } public Loader<Cursor> onCreateLoader(int id, Bundle args) { CursorLoader loader = new CursorLoader(this, ToDoContentProvider.CONTENT_URI, null, null, null, null); Log.e("GOPAL", "In the onCreateLoader"); return loader; } public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { int keyTaskIndex = cursor.getColumnIndexOrThrow(ToDoContentProvider.KEY_TASK); Log.e("GOPAL", "In the onLoadFinished"); todoItems.clear(); if (cursor.moveToNext() == false) Log.e("GOPAL", "Empty Cursor"); else { while (cursor.moveToNext()) { ToDoItem newItem = new ToDoItem(cursor.getString(keyTaskIndex)); todoItems.add(newItem); } aa.notifyDataSetChanged(); // aa is arrayadapter used for the listview } }

He leído, CursorLoader actualiza automáticamente la vista, siempre que haya un cambio de datos en el proveedor de contenido db. Eso significa que supongo que getLoaderManager().restartLoader(0, null, this) tiene que ser llamado implícitamente cada vez que hay un cambio en los datos, ¿verdad? Pero eso no está sucediendo. Cada vez que agrego un nuevo elemento (el elemento se agrega a la base de onNewItemAdded de onNewItemAdded , pero restartLoader no se llama explícitamente), pausa esta actividad y la reanuda. No veo ninguna llamada implícita a restartLoader (aunque se ha cambiado db) y la vista de lista tampoco se actualiza con el nuevo elemento agregado. ¿Porqué es eso? ¿Cómo actualiza CursorLoader la vista incluso si la aplicación no está activa? Gracias :)

EDITAR: También he usado getContext().getContentResolver().notifyChange(insertedId, null) en la inserción de mi proveedor de contenido.


Encontré la respuesta a mi pregunta. En general, CursorLoader no detecta automáticamente los cambios en los datos y los carga para verlos. Necesitamos rastrear la URI para los cambios. Esto se puede hacer siguiendo los pasos:

  1. Registrar un observador en la resolución de contenido mediante el cursor utilizando: (Hecho en el método de consulta de ContentProvider)
    cursor.setNotificationUri(getContext().getContentResolver(), uri);

  2. Ahora, cuando hay algún cambio en los datos subyacentes de URI usando insert() / delete() / update(), notificamos a ContentResolver sobre el cambio usando:

    getContext().getContentResolver().notifyChange(insertedId, null);

  3. Esto es recibido por el observador, nos registramos en el paso 1 y esto llama a ContentResolver.query() , que en ese momento llama al ContentResolver.query() ContentProvider para devolver un nuevo cursor al LoaderManager . LoaderManager llama onLoadFinished() pasando este cursor, junto con CursorLoader donde actualizamos la Vista (usando Adapter.swapCursor() ) con datos nuevos.

Para Custom AsyncTaskLoaders:

A veces necesitamos nuestro cargador personalizado en lugar de CursorLoader. Aquí podemos usar otro objeto que no sea el cursor para señalar los datos cargados (como la lista, etc.). En esto no tendremos previlige para notificar a ContentResolver a través del cursor. Es posible que la aplicación tampoco tenga un proveedor de contenido para rastrear los cambios de URI. En este escenario, utilizamos BroadcastReceiver o ContentObserver explícito para lograr la actualización automática de la vista. Esto es como sigue:

  1. Necesitamos definir nuestro cargador personalizado que extienda AsyncTaskLoader e implemente todos sus métodos abstractos. A diferencia de CursorLoader , nuestro Cargador personalizado puede o no usar un Proveedor de contenido y su constructor puede no llamar a ContentResolver.query() , cuando este cargador está inseguro. Así que usamos un receptor de difusión para cumplir el propósito.
  2. Necesitamos crear una instancia de un BroadCastReceiver o ContentObserver en OnStartLoading() de la clase AsyncTaskLoader abstracta.
  3. Este receptor BroadCast debe definirse para recibir transmisiones de cambio de datos del proveedor de contenido o cualquier evento del sistema (como la nueva aplicación instalada) y debe llamar al método onContentChanged() del cargador, para notificar al cargador sobre el cambio de datos. Loader automáticamente hace el resto para cargar los datos actualizados y llamar onLoadFinished() para actualizar la vista.

Para más detalles, consulte esto: http://developer.android.com/reference/android/content/AsyncTaskLoader.html

Encontré esto muy útil para una explicación clara: http://www.androiddesignpatterns.com/2012/08/implementing-loaders.html


obtener una referencia a su cargador mientras se inicializa de la siguiente manera

Loader dayWeatherLoader = getLoaderManager().initLoader(LOADER_DAY_WEATHER, null, this);

luego cree una clase que extienda ContentObserver de la siguiente manera

class DataObserver extends ContentObserver { public DataObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange, Uri uri) { dayWeatherLoader.forceLoad(); } }

Luego registre el observador de contenido dentro del método del ciclo de vida de Reanudar de la siguiente manera

@Override public void onResume() { super.onResume(); getContext().getContentResolver().registerContentObserver(CONTENTPROVIDERURI,true,new DayWeatherDataObserver(new Handler())); }

Siempre que haya un cambio en los datos subyacentes del proveedor de contenido, se llamará al método onChange de contentobserver donde puede solicitar al cargador que vuelva a cargar los datos.