uso de ContentProviderClient vs ContentResolver para acceder al proveedor de contenido


La documentación de sobre los proveedores de contenido de Android describe el uso de un ContentResolver, obtenido de getContentResolver(), para acceder al contenido.

Sin embargo, también hay un ContentProviderClient, que se puede obtener de getContentResolver().acquireContentProviderClient(authority). Parece proporcionar más o menos los mismos métodos disponibles en el ContentResolver para acceder al contenido del proveedor.

¿Cuándo debo usar un ContentProviderClient en lugar de solo usar el ContentResolver directamente? ¿Cuáles son los beneficios?

Author: Alex Lockwood, 2011-02-23

5 answers

Su dispositivo Android tiene muchas bases de datos, cada una de las cuales está identificada por una Autoridad de Contenido única. Esta es la parte equivalente del "nombre de dominio" en el contenido: / / uri everything todo antes de la primera barra.

ContentResolver almacena datos que proporcionan una asignación de String contentAuthority a ContentProvider. Cuando se llama a ContentResolver.query() o update() o lo que sea, el URI se analiza en sus componentes, se identifica la cadena contentAuthority, y ContentResolver tiene que buscar en ese mapa una cadena coincidente, y dirigir consulta al proveedor correcto. Esta búsqueda costosa ocurre durante cada llamada, porque el URI puede ser diferente de una llamada a otra, con una autoridad de contenido diferente también. Además, puede haber algunos costos involucrados en la configuración y el desmantelamiento de una conexión con ese proveedor específico't No se puede reutilizar entre llamadas. No estoy seguro de la sobrecarga involucrada allí, eso es un código de nivel de sistema operativo bastante profundo.

Por el contrario, cuando se llama acquireContentProviderClient(authority), que "¿qué proveedor hago ¿necesitas?"la búsqueda se hace una vez, y se le da un ContentProviderClient que es esencialmente un enlace directo a la ContentProvider. (Hay un poco de pegamento entre usted y el proveedor que implica la comunicación entre hilos y el bloqueo de concurrencia). Sin embargo, cuando utilice ContentProviderClient, hablará directamente con el Proveedor para obtener la autoridad que solicitó. Esto elimina el desperdicio de volver a calcular constantemente " ¿qué proveedor quiero?"

NOTA: Per acquireContentProviderClient() documentation: Si obtiene un ContentProviderClient, "El llamante debe indicar que ha terminado con el proveedor llamando a ContentProviderClient.release () que permitirá al sistema liberar al proveedor si determina que no hay otra razón para mantenerlo activo." Así que esencialmente, dejar un Cliente obsoleto abierto forzará al Proveedor a seguir ejecutándose como un servicio en segundo plano. Por lo tanto, recuerde limpiar!

Resumen:

Muchos llamadas a diferentes autoridades de contenido: Use ContentResolver.

Llamadas repetidas a la misma Autoridad: Obtener y usar ContentProviderClient. Recuerda liberarlo () cuando hayas terminado.

 90
Author: jcwenger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-05 22:27:29

Está bien, pero tenga en cuenta que solo funciona cuando ContentProvider se ejecuta en este mismo proceso que Activity.

Nota de la documentación para el método getLocalContentProvider():

Si el ContentProvider se está ejecutando en un proceso diferente, entonces null será devuelto. Esto se puede utilizar si usted sabe que se está ejecutando en el mismo proceso que un proveedor, y desea obtener acceso directo a su detalles de implementación.

 7
Author: Jokii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-24 11:55:47

Creo que la otra diferencia de importación es ContentProviderClient se puede convertir en su objeto proveedor personalizado y acceder a otro método además de CRUD.

ContentProvider cp = getContentResolver().acquireContentProviderClient(mCurUri).getLocalContentProvider();
yourProvider fld = (yourProvider)cp;
fld.query(...);           // you can query as ContentResolver
fld.addFolder(newFolder); // also can invoke the extend method of your custom ContentProvider
 4
Author: guangmao.yu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-05 22:26:35

Encontré la siguiente diferencia: Escribí mi propio contentprovider personalizado en la aplicación A. Escribí un widget de pantalla de inicio en la aplicación B. Cuando intenté acceder al ContentProvider de la aplicación A a través de un ContentResolver desde mi widget, recibí un error "no pude encontrar la información del proveedor". Cuando en su lugar adquiriría un ContentProviderClient a través del ContentResolver y consultaría a través del ContentProviderClient, funcionaría. No tuve que cambiar nada más, solo usar el ContentProviderClient en lugar del ContentResolver. No tengo ninguna explicación real para ese comportamiento y no he encontrado información en Internet, en cuanto a por qué es así. No sé, si esto es una peculiaridad especial de los widgets, porque no lo intenté desde una actividad en la aplicación B (aplicación B es un mero widget, sin actividad).

 2
Author: mrd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-09 21:17:29

Uno de los usos de ContentProviderClient es útil para acceder a algunos de los métodos de ContentProvider en pruebas. Por ejemplo, utilizo el método shutdown() en pruebas unitarias para evitar que varias pruebas instancien varios proveedores de contenido.

Implementar ContentProvider#shutdown() así:

@Override
public void shutdown() {
    openHelper.close();
    super.shutdown();
}

Y al final del método de prueba, llame a shutdown() usando el ContentProviderClient para limpiar la prueba para que otras pruebas puedan usar el proveedor de contenido:

getContext()
       .getContentResolver()
       .acquireContentProviderClient(URI)
       .getLocalContentProvider()
       .shutdown();
 0
Author: Yogesh Umesh Vaity,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-08 13:32:03