Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Prácticas recomendadas para exponer varias tablas mediante proveedores de contenido en Android

Estoy construyendo una aplicación donde tengo una mesa para eventos y una mesa para lugares. Quiero poder conceder a otras aplicaciones el acceso a estos datos. Tengo algunas preguntas relacionadas con las mejores prácticas para este tipo de problema.

  1. ¿Cómo debo estructurar las clases de la base de datos? Actualmente tengo clases para EventsDbAdapter y VenuesDbAdapter, que proporcionan la lógica para consultar cada tabla, mientras que tiene un DbManager separado (extiende SQLiteOpenHelper) para administrar versiones de bases de datos, crear / actualizar bases de datos, dando acceso a base de datos (getWriteable / ReadeableDatabase). ¿Es esta la solución recomendada, o sería mejor consolidar todo a una clase (es decir, el DbManager) o separar todo y dejar que cada adaptador extienda SQLiteOpenHelper?

  2. ¿Cómo debo diseñar proveedores de contenido para múltiples tablas? Si amplía la pregunta anterior, ¿debo usar un proveedor de contenido para la aplicación completa o debo crear proveedores independientes para eventos y lugares?

La mayoría de los ejemplos que encuentro sólo se ocupan de aplicaciones de tabla única, por lo que apreciaría cualquier punteros aquí.

  • Problemas en la creación de varias tablas en sqlite
  • Android: java.lang.IllegalStateException: base de datos xxx.db (conn # 0) ya cerrado
  • Cómo imprimir la consulta ejecutada por el método query () de android
  • ¿Cómo realizar una consulta SQLite dentro de una aplicación de Android?
  • Java.lang.OutOfMemoryError en almacenar imágenes en sqlite db
  • Ordenar una lista en orden ascendente por fecha desde sqlite
  • Android Seleccionar fila por Id en Sqlite?
  • ¿Cómo acceder a una base de datos sqlite existente en Android?
  • 4 Solutions collect form web for “Prácticas recomendadas para exponer varias tablas mediante proveedores de contenido en Android”

    Es probablemente un poco tarde para usted, pero otros pueden encontrar esto útil.

    Primero debe crear múltiples CONTENT_URIs

    public static final Uri CONTENT_URI1 = Uri.parse("content://"+ PROVIDER_NAME + "/sampleuri1"); public static final Uri CONTENT_URI2 = Uri.parse("content://"+ PROVIDER_NAME + "/sampleuri2"); 

    A continuación, amplíe su URI Matcher

     private static final UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(PROVIDER_NAME, "sampleuri1", SAMPLE1); uriMatcher.addURI(PROVIDER_NAME, "sampleuri1/#", SAMPLE1_ID); uriMatcher.addURI(PROVIDER_NAME, "sampleuri2", SAMPLE2); uriMatcher.addURI(PROVIDER_NAME, "sampleuri2/#", SAMPLE2_ID); } 

    Luego crea tus tablas

     private static final String DATABASE_NAME = "sample.db"; private static final String DATABASE_TABLE1 = "sample1"; private static final String DATABASE_TABLE2 = "sample2"; private static final int DATABASE_VERSION = 1; private static final String DATABASE_CREATE1 = "CREATE TABLE IF NOT EXISTS " + DATABASE_TABLE1 + " (" + _ID1 + " INTEGER PRIMARY KEY AUTOINCREMENT," + "data text, stuff text);"; private static final String DATABASE_CREATE2 = "CREATE TABLE IF NOT EXISTS " + DATABASE_TABLE2 + " (" + _ID2 + " INTEGER PRIMARY KEY AUTOINCREMENT," + "data text, stuff text);"; 

    No olvide agregar el segundo DATABASE_CREATE a onCreate()

    Va a utilizar un bloque de mayúsculas y minúsculas para determinar qué tabla se utiliza. Este es mi código de inserto

     @Override public Uri insert(Uri uri, ContentValues values) { Uri _uri = null; switch (uriMatcher.match(uri)){ case SAMPLE1: long _ID1 = db.insert(DATABASE_TABLE1, "", values); //---if added successfully--- if (_ID1 > 0) { _uri = ContentUris.withAppendedId(CONTENT_URI1, _ID1); getContext().getContentResolver().notifyChange(_uri, null); } break; case SAMPLE2: long _ID2 = db.insert(DATABASE_TABLE2, "", values); //---if added successfully--- if (_ID2 > 0) { _uri = ContentUris.withAppendedId(CONTENT_URI2, _ID2); getContext().getContentResolver().notifyChange(_uri, null); } break; default: throw new SQLException("Failed to insert row into " + uri); } return _uri; } 

    Tendrás que configurar la delete , update , getType , etc. Dondequiera que tu proveedor llame a DATABASE_TABLE o CONTENT_URI agregará un caso y tendrá DATABASE_TABLE1 o CONTENT_URI1 en uno y # 2 en el siguiente y así sucesivamente para tantos como quieras .

    Le recomiendo que consulte el código fuente para el Android 2.x ContactProvider. (Que se puede encontrar en línea). Ellos manejan las consultas de tabla cruzada, proporcionando vistas especializadas que luego ejecutar consultas contra en el extremo posterior. En el extremo frontal son accesibles para el llamador a través de diferentes URI diferentes a través de un único proveedor de contenido. Probablemente también desee proporcionar una clase o dos para mantener constantes para los nombres de campos de tabla y las cadenas de URI. Estas clases se pueden proporcionar ya sea como una API o como una caída en la clase, y hará que sea mucho más fácil para la aplicación consumir a utilizar.

    Es un poco complejo, por lo que también puede desear comprobar cómo el calendario también para tener una idea de lo que hace y no necesita.

    Sólo debe necesitar un único adaptador de DB y un solo proveedor de contenido por base de datos (no por tabla) para realizar la mayor parte del trabajo, pero puede utilizar varios adaptadores / proveedores si realmente lo desea. Simplemente hace las cosas un poco más complicadas.

    Un ContentProvider puede servir varias tablas, pero deben estar algo relacionadas. Hará una diferencia si piensa sincronizar sus proveedores. Si desea sincronizaciones separadas para, por ejemplo, Contactos, Correo o Calendario, necesitará diferentes proveedores para cada uno de ellos, incluso si terminan en la misma base de datos o se sincronizan con el mismo servicio, ya que los adaptadores de sincronización están vinculados directamente a Un proveedor particular.

    Por lo que puedo decir, sólo puede utilizar un solo SQLiteOpenHelper por base de datos, ya que almacena su meta información en una tabla dentro de la base de datos. Así que si los ContentProviders acceden a la misma base de datos, tendrás que compartir el Ayudante de alguna manera.

    Nota: Esta es una aclaración / modificación de la respuesta proporcionada por Opy.

    Este enfoque subdivide cada uno de los métodos insert , delete , update y getType con instrucciones switch para manejar cada una de sus tablas individuales. Utilizará un CASE para identificar cada tabla (uri) a la que se hará referencia. Cada CASO entonces asigna a una de sus tablas o URI's. Por ejemplo, TABLE1 o URI1 se selecciona en el CASO # 1, etc. para todas las tablas que emplea su aplicación.

    Aquí hay un ejemplo del enfoque. Esto es para el método de inserción. Se implementa un poco diferente de Opy pero realiza la misma función. Puede seleccionar el estilo que prefiera. También quería asegurar que el inserto devuelve un valor incluso si falla la inserción de la tabla. En ese caso devuelve -1 .

      @Override public Uri insert(Uri uri, ContentValues values) { int uriType = sURIMatcher.match(uri); SQLiteDatabase sqlDB; long id = 0; switch (uriType){ case TABLE1: sqlDB = Table1Database.getWritableDatabase(); id = sqlDB.insert(Table1.TABLE_NAME, null, values); getContext().getContentResolver().notifyChange(uri, null); return Uri.parse(BASE_PATH1 + "/" + id); case TABLE2: sqlDB = Table2Database.getWritableDatabase(); id = sqlDB.insert(Table2.TABLE_NAME, null, values); getContext().getContentResolver().notifyChange(uri, null); return Uri.parse(BASE_PATH2 + "/" + id); default: throw new SQLException("Failed to insert row into " + uri); return -1; } } // [END insert] 
    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.