2010-11-20 9 views
18

La mia app utilizza due database (file separati). Per gestire questi database ho creato due classi Helper che estendono SQLiteOpenHelper, una per ogni database.Android: posso utilizzare una classe SQLiteOpenHelper per più file di database?

Ora aggiungo un terzo database e mi chiedo se è necessario creare un'altra classe Helper (e se ho usato un quarto e un quinto database avrei bisogno di ancora più classi Helper) o posso usare lo stesso Classe di supporto per più database?

Il problema che vedo cercando di utilizzare una sola classe Helper è che non riesco a vedere come passare il nome dei singoli file di database a Helper. Attualmente il nome del database è hard-coded come un campo statico di ciascuna classe Helper, ma se avessi una sola classe Helper avrei bisogno di essere in grado di passare i diversi nomi al Costruttore quando si crea il Helper separato oggetti; il problema è che SQLiteOpenHelper Constructor sembra essere chiamato da Android con un solo parametro: il Contesto.

+0

Hey man! Sto facendo qualcosa di molto simile a te, ma nel mio caso ho bisogno di 2 diverse classi dbHelper. Il fatto è che sto ricevendo un errore mentre cercavo di farlo. java.lang.IllegalStateException: la classe Helper era di classe X ma sta cercando di essere reimpostata sulla classe Y. hai mai dovuto affrontare questo problema? – Ajay

risposta

16

Naturalmente, è possibile. È solo una questione di design della tua classe Helper. Si può solo passare il nome di DB al costruttore della classe Helper (insieme a richiesta Context esempio), invece di hardcoding:

public class DBOpenHelper extends SQLiteOpenHelper { 

    public DBOpenHelper(Context context, String dbName, int dbVersion) { 
     super(context, dbName, null, dbVersion); 
    } 
... 
} 
+0

Silly me! Non stavo leggendo il mio codice di creazione di codice oggetto Helper correttamente. Come dici tu, è molto semplice. – prepbgg

+0

Ciao, vorrei fare una domanda (spero che non sia troppo semplice/ovvio) che è come si fa a scorrere la classe helper per creare tutti i database? Sei passato in rassegna la classe helper usando un ciclo for per il numero di database che vuoi creare e passare in tutti i nomi dei database? – jamen

2

È necessaria una classe astratta che implementa il processo di aggiornamento qui descritto. Quindi estendi questa classe astratta per ciascuna delle tue tabelle. Nella classe astratta è necessario archiviare le tabelle in un modo (elenco, hardcoded), quindi quando onUpgrade esegue l'iterazione sugli elementi della tabella e per ciascun elemento della tabella si eseguono i passaggi descritti. Verranno aggiornati autonomamente, mantenendo tutti i dettagli esistenti. Tieni presente che l'evento onUpgrade si attiva una sola volta per database, ecco perché è necessario scorrere tutte le tabelle per eseguire l'aggiornamento di tutte. Si mantiene solo 1 numero di versione su tutto il database.

  • beginTransaction
  • corsa creazione tabella con if not exists (stiamo facendo un aggiornamento, in modo che la tabella potrebbe non esiste ancora, falliremo alterare e drop)
  • messo in una lista le colonne esistenti List<String> columns = DBUtils.GetColumns(db, TableName);
  • tabella di backup (ALTER table " + TableName + " RENAME TO 'temp_" + TableName)
  • creare nuova tabella (il più recente schema di creazione della tabella)
  • ottenere l'incrocio con le nuove colonne, questo colonne prendere tempo n dalla tabella aggiornata (columns.retainAll(DBUtils.GetColumns(db, TableName));)
  • ripristino dei dati (String cols = StringUtils.join(columns, ","); db.execSQL(String.format( "INSERT INTO %s (%s) SELECT %s from temp_%s", TableName, cols, cols, TableName)); )
  • tabella di backup remove (DROP table 'temp_" + TableName)
  • setTransactionSuccessful

(Questo non gestisce tavolo downgrade, se si rinomina una colonna , non si ottiene il trasferimento dei dati esistenti poiché i nomi delle colonne non corrispondono).

.

public static List<String> GetColumns(SQLiteDatabase db, String tableName) { 
    List<String> ar = null; 
    Cursor c = null; 
    try { 
     c = db.rawQuery("select * from " + tableName + " limit 1", null); 
     if (c != null) { 
      ar = new ArrayList<String>(Arrays.asList(c.getColumnNames())); 
     } 
    } catch (Exception e) { 
     Log.v(tableName, e.getMessage(), e); 
     e.printStackTrace(); 
    } finally { 
     if (c != null) 
      c.close(); 
    } 
    return ar; 
} 

public static String join(List<String> list, String delim) { 
    StringBuilder buf = new StringBuilder(); 
    int num = list.size(); 
    for (int i = 0; i < num; i++) { 
     if (i != 0) 
      buf.append(delim); 
     buf.append((String) list.get(i)); 
    } 
    return buf.toString(); 
} 
+0

Ho paura che questo sia troppo complicato per me! Forse dovrei restare con più classi Helper per più database. – prepbgg

+0

Hai tutti i frammenti di codice complicati lì. Devi solo avvolgere in un ciclo for e avvolgere le transazioni in giro. Ci sono cose più complicate di così. – Pentium10

Problemi correlati