2012-04-10 4 views
7

Sto provando a interrogare tutte le colonne di una tabella in una lunga vista di testo e/o una stringa. So che questo potrebbe non essere il modo giusto di fare le cose, ma devo farlo. Correggetemi se sbaglio, ho avuto l'impressione che la prossima mossa otterrebbe la colonna successiva nella riga:android cursor.moveToNext()?

Cursor c = db.get(); 
if(c.moveToFirst){ 
do{ 
string = c.getString(0); 
}while(c.moveToNext); 

ho pensato che questo sarebbe ottenere la prima colonna e visualizzare tutti i suoi contenuti, invece ho la prima colonna e prima riga. Che cosa sto facendo di sbagliato? C'è un modo migliore o reale per ottenere queste informazioni senza utilizzare un ListView?

risposta

9

Per chiarezza un esempio completo sarebbe il seguente che mi fido è di interesse. Come indicato nei commenti al codice, essenzialmente eseguiamo iterazioni su righe di database e quindi su colonne per formare una tabella di dati come da database.

Cursor cursor = getActivity().getContentResolver().query(uri, projection, null, null, 
      null); 

    //if the cursor isnt null we will essentially iterate over rows and then columns 
    //to form a table of data as per database. 
    if (cursor != null) { 

     //more to the first row 
     cursor.moveToFirst(); 

     //iterate over rows 
     for (int i = 0; i < cursor.getCount(); i++) { 

      //iterate over the columns 
      for(int j = 0; j < cursor.getColumnNames().length; j++){ 

       //append the column value to the string builder and delimit by a pipe symbol 
       stringBuilder.append(cursor.getString(j) + "|"); 
      } 
      //add a new line carriage return 
      stringBuilder.append("\n"); 

      //move to the next row 
      cursor.moveToNext(); 
     } 
     //close the cursor 
     cursor.close(); 
    } 
1

moveToNext sposta il cursore sulla riga successiva. e c.getString (0) ti darà sempre la prima colonna se ce n'è una. Credo che si dovrebbe fare qualcosa di simile a questo all'interno del vostro ciclo

int index = c.getColumnIndex("Column_Name"); 
string = c.getString(index); 
1

cursor.moveToFirst() sposta il cursore alla prima riga. Se sai che hai 6 colonne e vuoi una stringa contenente tutte le colonne, prova quanto segue.

c.moveToFirst(); 
StringBuilder stringBuilder = new StringBuilder(); 
for(int i = 0; i < 6; i++){ 
    stringBuilder.append(c.getString(i)); 
} 

// to return the string, you would do stringBuilder.toString(); 
+1

E se non si conosce il numero di colonne, basta usare 'c.getColumnCount()' nel ciclo 'for'. – Squonk

0

sto una marcatura di miei loop sul cusror in questo modo:

cursor.moveToFirst(); 
    while(!cursor.isAfterLast()) { 

      cursor.getString(cursor.getColumnIndex("column_name")); 

     cursor.moveToNext(); 
    } 

che funziona sempre. Ciò recupererà i valori della colonna "nome_colonna" di tutte le righe. L'errore è che si esegue il loop sulle righe e non sulle colonne. Per ciclo su colonne:

cursor.moveToFirst();  
    for(int i = 0; i < cursor.getColumnNames().length; i++){ 
     cursor.getString(i); 
    } 

in loop sulle colonne della prima riga e recuperare ogni colonna.

30

L'uso è semplice:

Cursor cursor = db.query(...); 
while (cursor.moveToNext()) { 
    ... 
} 

moveToFirst viene utilizzato quando è necessario iniziare l'iterazione dall'inizio dopo aver già raggiunto una certa posizione.

Evitare di utilizzare cursor.getCount() tranne se richiesto. E non utilizzare mai un ciclo su getCount().

getCount è costoso - itera su molti record per contarli. Non restituisce una variabile memorizzata. Potrebbe esserci del caching in una seconda chiamata, ma la prima chiamata non conosce la risposta fino a quando non viene contata.

Se la query corrisponde a 1000 righe, il cursore ha effettivamente solo la prima riga. Ogni spostamentoToNext cerca e trova la prossima partita. getCount deve trovare tutti i 1000. Perché iterare su tutti se hai solo bisogno di 10? Perché ripetere l'iterazione due volte?

Inoltre, se la query non utilizza un indice, getCount potrebbe essere ancora più lento - getCount può superare i 10000 record anche se la query corrisponde solo a 100. Perché eseguire il ciclo 20000 anziché 10000?

+1

A partire da Android 4.2, 'moveToNext()' è implementato da 'moveToPosition()' che [chiama anche '.getCount()'] (http: // androidxref.com/4.2.2_r1/riferimento esterno/quadri/base/core/java/android/database/AbstractCursor.java # moveToPosition). Sicuramente questo è solo un dettaglio di implementazione su cui non bisogna fare affidamento. – kennytm

+1

@KennyTM ha ragione. In effetti questo era il caso anche prima di Android 4.2 (vedi http://bit.ly/1s8KClM). Inoltre, oltre a 'moveToNext()' praticamente tutte le altre operazioni di base del cursore (ad esempio 'moveToFirst()', 'isBeforeFirst()' e 'isFirst()') coinvolgono le chiamate a 'getCount()'. Quindi, anche se 'getCount()' è costoso, è inevitabile. Inoltre, l'implementazione di 'getCount()' memorizza nella cache il valore restituito, quindi almeno le chiamate successive saranno economiche (vedi http://bit.ly/1uL4ZEp). – Matthias