Autore Topic: Content provider... ultimi dubbi... poi la sincronizzazione?  (Letto 488 volte)

Offline Brig

  • Nuovo arrivato
  • *
  • Post: 17
  • Respect: +1
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S
  • Sistema operativo:
    Ubuntu 10.4, Windows 7
Content provider... ultimi dubbi... poi la sincronizzazione?
« il: 07 Dicembre 2011, 20:38:27 CET »
0
Salve a tutti!

Ho realizzato un database contenente 3 tabelle (con i relativi campi):
- T1[_id, idRelativoT2, idRelativoT3, lon, lat];
- T2[_id, nome, ele, isArea, tip, description];
- T3[_id, nome]

Dove T3 dovrebbe venir caricata all'inizio (quindi usata una sola volta) creando un String[] dove ad ogni indice corrisponde un nome. Il campo _id di T2 == idRelativoT2, lo stesso per T3.
Visto che il database dovrebbe essere utilizzato solo in lettura, sono stati implementati solo i metodi query e getType della mia classe estendente contentProvider; gli altri metodi sono "vuoti"..

Volevo chiedervi se ciò che ho scritto è corretto, perché non ho mai visto esempi che usino più di una tabella... anzi... a dirla tutta ho visto praticamente solo esempi che usano i contatti telefonici o dei libri....

Codice (Java): [Seleziona]
package com.MyProject.providers;

import android.content.ContentResolver;
import android.net.Uri;
import android.provider.BaseColumns;

public class MyDatabaseSchema {

        public static class T1 implements BaseColumns{
                public final static String TABLE_NAME = "T1";
                public final static int CODE_TABLE = 1000;
                public final static Uri URI = Uri.parse("content://" + MyContentProvider.AUTHORITY + TABLE_NAME);
                public final static String TYPE = "vnd.android.cursor.dir/vnd." + TABLE_NAME;
               
                public final static String FIELD_ID = "_id";
                public final static String FIELD_INDEX_T2 = "idRelativoT2";
                public final static String FIELD_INDEX_T3 = "idRelativoT3";
                public final static String FIELD_LAT = "lat";
                public final static String FIELD_LON = "lon";  
        }

        public static class T2 implements BaseColumns{
                public final static String TABLE_NAME = "T2";
                public final static int CODE_TABLE = 2000;
                public final static Uri URI = Uri.parse("content://" + ContentProviderMapObject.AUTHORITY + TABLE_NAME);
                public final static String TYPE = "vnd.android.cursor.dir/vnd." + TABLE_NAME;
               
                public final static String FIELD_ID = "_id";
                public final static String FIELD_NAME = "nameT2";
                public final static String FIELD_ELE = "ele";
                public final static String FIELD_IS_AREA = "isArea";
                public final static String FIELD_TIP = "tip";
                public final static String FIELD_DESCRIPTION = "description";
        }

        public static class T3 implements BaseColumns{
                public final static String TABLE_NAME = "T3";
                public final static int CODE_TABLE = 3000;
                public final static Uri URI = Uri.parse("content://" + ContentProviderMapObject.AUTHORITY + TABLE_NAME);
                public final static String TYPE = "vnd.android.cursor.dir/vnd." + TABLE_NAME;
               
                public final static String FIELD_ID = "_id";
                public final static String FIELD_NAME = "nameT3";
        }
}

Codice (Java): [Seleziona]
public class MyContentProvidert extends ContentProvider {
        private static class DatabaseHelper extends SQLiteOpenHelper{
                private static final String DATABASE_PATH = "/pathDatabase/";
                private static final String DATABASE_NAME = "database.sqlite";
                private static final int DATABASE_VERSION = 3;
                private static final File DATABASE_FILE = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), DATABASE_PATH + DATABASE_NAME);
               
                public DatabaseHelper(Context context) {
                        super(context, DATABASE_FILE.getAbsolutePath(), null, DATABASE_VERSION);
                }
                public void onCreate(SQLiteDatabase arg0) { ; }
                public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) { ; }
        }
       
        public final static String AUTHORITY = "com.myProject.providers.MyContentProvider"; // il pakadge è: com.myProject.providers, il nome della classe: MyContentProvider
       

        private SQLiteDatabase db;
        private static HashMap<String, String> mapObject;
    private static final UriMatcher uriMatcher;
        static {
                uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
               
                uriMatcher.addURI(AUTHORITY, MyDatabaseSchema.NAME_TABLE_T1, MyDatabaseSchema.CODE_TABLE_T1);
                uriMatcher.addURI(AUTHORITY, MyDatabaseSchema.NAME_TABLE_T2, MyDatabaseSchema.CODE_TABLE_T2);
                uriMatcher.addURI(AUTHORITY, MyDatabaseSchema.NAME_TABLE_T3, MyDatabaseSchema.CODE_TABLE_T3);
       
                mapObject = new HashMap<String, String>();
       
                mapObjectProjectionMap.put(MyDatabaseSchema.T2.FIELD_DESCRIPTION, MyDatabaseSchema.T2.FIELD_DESCRIPTION);
                mapObjectProjectionMap.put(MyDatabaseSchema.T2.FIELD_ELE, MyDatabaseSchema.T2.FIELD_ELE);
                mapObjectProjectionMap.put(MyDatabaseSchema.T1.FIELD_INDEX_T3, MyDatabaseSchema.T1.FIELD_INDEX_T3);
                mapObjectProjectionMap.put(MyDatabaseSchema.T1.FIELD_INDEX_T2, MyDatabaseSchema.T1.FIELD_INDEX_T2);
                mapObjectProjectionMap.put(MyDatabaseSchema.T2.FIELD_IS_AREA, MyDatabaseSchema.T2.FIELD_IS_AREA);
                mapObjectProjectionMap.put(MyDatabaseSchema.T1.FIELD_LAT, MyDatabaseSchema.T1.FIELD_LAT);
                mapObjectProjectionMap.put(MyDatabaseSchema.T1.FIELD_LON, MyDatabaseSchema.T1.FIELD_LON);
                mapObjectProjectionMap.put(MyDatabaseSchema.T2.FIELD_NAME, MyDatabaseSchema.T2.FIELD_NAME);
                mapObjectProjectionMap.put(MyDatabaseSchema.T3.FIELD_NAME, MyDatabaseSchema.T3.FIELD_NAME);
                mapObjectProjectionMap.put(MyDatabaseSchema.T2.FIELD_TIP, MyDatabaseSchema.T2.FIELD_TIP);              

        }
       
        public String getType(Uri uri) {
                switch (uriMatcher.match(uri)) {
                        case MyDatabaseSchema.T1.CODE_TABLE:
                                return MyDatabaseSchema.T1.TYPE;
                        case MyDatabaseSchema.T2.CODE_TABLE:
                                return MyDatabaseSchema.T2.TYPE;
                        case MyDatabaseSchema.T3.CODE_TABLE:
                                return MyDatabaseSchema.T3.TYPE;
                        default:
                                throw new IllegalArgumentException("Unknown URI " + uri);
                }
        }

        @Override
        public boolean onCreate() {
                db = (new DatabaseHelper(getContext())).getReadableDatabase();
                return false;
        }

        @Override
        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
                String table = null;           
                switch(uriMatcher.match(uri)){
                        case MyDatabaseSchema.T1.CODE_TABLE:
                                table = MyDatabaseSchema.T1.TABLE_NAME;
                        break;
                        case MyDatabaseSchema.T2.CODE_TABLE
                                table = MyDatabaseSchema.T2.NAME_TABLE;
                        break;
                        case MyDatabaseSchema.T3.CODE_TABLE:
                                table = MyDatabaseSchema.T3.NAME_TABLE;
                        break;
                        default:
                throw new IllegalArgumentException("Unknown URI " + uri);
                }
                SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
                qb.setTables(table);
                qb.setProjectionMap(mapObjectProjectionMap);
                Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, sortOrder);
                c.setNotificationUri(getContext().getContentResolver(), uri);
                return c;
        }
}

fin qui come vi sembra?

ora viene il problema "concorrenza"... dato che è un db da 2.9MB ci sta qualche secondo a creare un readbleDatabase... (cosa che ho visto fare in ogni esempio del metodo query())...  questo ne rallenterebbe molto l'esecuzione... purtroppo però se si fanno due invocazioni di query() la seconda modifica il cursore al primo... quindi si dovrebbe usare un solo cursore... peccato però che non si può determinare quando viene chiuso l'ultimo precedentemente aperto...
copiare i dati del cursore in memoria e rilasciare quella struttura dati potrebbe essere pesante in termini di memoria... la creazione di un buffer di database readble usa e getta probabilmente comporterebbe un'altro spreco di memoria..
avete qualche soluzione?

p.s. giusto per curiosità... ma essendo il contentProvider "disponibile" a più applicazioni, se due diverse, "nello stesso momento" effettuassero query diverse, andrebbero a modificarsi i cursori a vicenda no?

p.p.s. non lo ho ancora provato perché volevo essere convinto della correttezza logica del codice
« Ultima modifica: 08 Dicembre 2011, 00:38:04 CET da Brig »