oncreateloader loaders initloader getloadermanager android cursor android-3.0-honeycomb android-loadermanager

initloader - loaders en android



¿Cuáles son los beneficios de CursorLoaders? (2)

Hay dos ventajas clave para usar un CursorLoader en su aplicación sobre Activity.managedQuery() :

  1. La consulta se maneja en un subproceso en segundo plano para usted (cortesía de la compilación en AsyncTaskLoader ) para que las consultas de datos grandes no bloqueen la interfaz de usuario. Esto es algo que los documentos recomiendan que hagas por ti mismo cuando usas un Cursor plano, pero ahora está hecho bajo el capó.
  2. CursorLoader se actualiza automáticamente. Además de realizar la consulta inicial, el CursorLoader registra un ContentObserver con el conjunto de datos que solicitó y llama a forceLoad() sobre sí mismo cuando cambia el conjunto de datos. Esto da como resultado que obtenga devoluciones de llamada asíncronas en cualquier momento en que los datos cambien para actualizar la vista.

Cada instancia de Loader también se maneja a través del LoaderManager singular, por lo que aún no tiene que administrar el cursor directamente, y ahora la conexión puede persistir incluso más allá de una sola Activity . LoaderManager.initLoader() y LoaderManager.restartLoader() permiten reconectarse con un Loader existente ya configurado para su consulta y, en algunos casos, obtener instantáneamente los datos más recientes, si están disponibles.

Su Activity o Fragment probablemente ahora implementará la interfaz LoaderManager.Callback . Al llamar a initLoader() se onCreateLoader() método onCreateLoader() donde construirá la consulta y una nueva instancia de CursorLoader , si es necesario. El método onLoadFinished() se activará cada vez que haya nuevos datos disponibles, e incluirá el Cursor más reciente para que se adjunte a la vista o se realice una iteración.

Además, hay un buen ejemplo de todo este ajuste en la página de documentación de la clase LoaderManager : http://developer.android.com/reference/android/app/LoaderManager.html

¡Espero que ayude!

Utilizo los Cursors ampliamente en mi aplicación para cargar y ocasionalmente escribir información desde y hacia una base de datos. He visto que Honeycomb y el paquete de compatibilidad tienen nuevas clases de Loader diseñadas para ayudar a cargar datos de una manera "buena".

Básicamente, ¿son estas nuevas clases (en particular CursorLoader ) considerablemente mejores que los métodos anteriores de administración de datos? ¿Cuál es el beneficio de un CursorLoader sobre los Cursors administrados, por ejemplo?

Y utilizo un ContentProvider para tratar con los datos, que obviamente toma Uris pero ¿cómo encaja esto con el método initLoader() ? ¿Debo configurar cada uno de mis Fragments para usar los Cargadores individualmente? ¿Y qué tan único debe ser el ID para cada cargador, está sobre el alcance de mi aplicación o solo un fragmento? ¿Hay alguna forma sencilla de pasar un Uri a un CursorLoader para consultar mis datos?

Todo lo que puedo ver en este momento es que los Cargadores agregan un paso adicional innecesario para incluir mis datos en mi aplicación, ¿puede alguien explicármelos mejor?


Si alguien se encuentra en una situación similar, esto es lo que he hecho:

  • Creó una clase que implementa LoaderCallbacks y maneja todas las consultas que necesitará.
  • Suministre esto con un Context y el Adapter en cuestión.
  • Cree identificadores únicos para cada consulta que usará (si usa un UriMatcher , también podría usar los mismos)
  • Haga un método conveniente que transfiera las consultas al paquete requerido para las LoaderCallbacks
  • Eso es más o menos :) Pongo parte de mi código a continuación para mostrar exactamente lo que hice

En mi clase de GlobalCallbacks :

public static final String PROJECTION = "projection"; public static final String SELECTION = "select"; public static final String SELECTARGS = "sargs"; public static final String SORT = "sort"; Context mContext; SimpleCursorAdapter mAdapter; public GlobalCallbacks(Context context, SimpleCursorAdapter adapter) { mContext = context; mAdapter = adapter; } @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { Uri contentUri = AbsProvider.customIntMatch(id); if (contentUri != null) { return new CursorLoader(mContext, contentUri, args.getStringArray(PROJECTION), args.getString(SELECTION), args.getStringArray(SELECTARGS), args.getString(SORT)); } else return null; } @Override public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) { mAdapter.swapCursor(arg1); } @Override public void onLoaderReset(Loader<Cursor> arg0) { mAdapter.swapCursor(null); }

Y cuando quise usar un CursorLoader ( Helper.bundleArgs() es el método de agrupación conveniente):

scAdapt = new Adapters.NewIndexedAdapter(mHost, getMenuType(), null, new String[] { "name" }, new int[] { android.R.id.text1 }); getLoaderManager().initLoader( GlobalCallbacks.GROUP, Helper.bundleArgs(new String[] { "_id", "name" }), new GlobalCallbacks(mHost, scAdapt)); setListAdapter(scAdapt);

Y en ayudante:

public static Bundle bundleArgs(String[] projection, String selection, String[] selectionArgs) { Bundle b = new Bundle(); b.putStringArray(GlobalCallbacks.PROJECTION, projection); b.putString(GlobalCallbacks.SELECTION, selection); b.putStringArray(GlobalCallbacks.SELECTARGS, selectionArgs); return b; }

Espero que esto ayude a alguien más :)

EDITAR

Para explicar más a fondo:

  • Primero, se inicializa un adaptador con un Cursor nulo. No lo suministramos con un Cursor porque GlobalCallbacks le dará al adaptador el Cursor correcto en onLoadFinished(..)
  • A continuación, le decimos a LoaderManager que queremos inicializar un nuevo CursorLoader . Proporcionamos una nueva instancia de GlobalCallbacks (que implementa Loader.Callbacks ) que luego monitoreará la carga del cursor. También tenemos que suministrarlo con el adaptador, para que pueda intercambiar el nuevo Cursor una vez que se haya cargado. En algún momento, el LoaderManager (que está integrado en el sistema operativo) invocará onCreateLoader(..) de GlobalCallbacks y comenzará a cargar datos de forma asíncrona.
  • Helper.bundleArgs(..) simplemente coloca los argumentos para la consulta en un Bundle (por ejemplo, proyección de columnas, orden de clasificación, cláusula WHERE)
  • Luego configuramos el ListAdapter lista del Fragment . El cursor seguirá siendo nulo en este punto, por lo que mostrará un signo de carga o un mensaje vacío hasta que se onLoadFinished()