android - dipartimento di chimica




La colonna "_id" di Android non esiste? (6)

Ciò che ha risolto il mio problema con questo errore era che non avevo incluso la colonna _id nella mia query DB. Aggiungendo quello risolto il mio problema.

Ho problemi con qualcosa che funziona nell'esempio Notepad. Ecco il codice da NotepadCodeLab / Notepadv1Solution:

String[] from = new String[] { NotesDbAdapter.KEY_TITLE };
int[] to = new int[] { R.id.text1 };

SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
R.layout.notes_row, c, from, to);

Questo codice sembra funzionare correttamente. Ma per essere chiari, ho eseguito l'utilità ADB ed eseguito SQLite 3. Ho ispezionato lo schema come segue:

sqlite> .schema

CREATE TABLE android_metadata (locale TEXT);
CREATE TABLE notes (_id integer primary key autoincrement, title text
not null, body text not null);

Tutto sembra buono per me.

Ora sulla mia applicazione, che, per quanto posso vedere, è fondamentalmente la stessa con alcune modifiche minori. Ho semplificato e semplificato il mio codice, ma il problema persiste.

String[] from = new String[] { "x" };
int[] to = new int[] { R.id.x };

SimpleCursorAdapter adapter = null;
try
{
    adapter = new SimpleCursorAdapter(this, R.layout.circle_row, cursor, from, to);
}
catch (RuntimeException e)
{
    Log.e("Circle", e.toString(), e);
}

Quando eseguo la mia applicazione, ottengo una RuntimeException e le seguenti stampe in LogCat dalla mia Log.e() :

LogCat Message:

java.lang.IllegalArgumentException: la colonna '_id' non esiste

Quindi, torna a SQLite 3 per vedere cosa c'è di diverso sul mio schema:

sqlite> .schema CREATE TABLE android_metadata (locale TEXT); Cerchi CREATE TABLE (_id integer autoincrement chiave primaria, numero intero di sequenze, raggio reale, x reale, reale);

Non vedo come mi manca il '_id'.

Cosa ho fatto di sbagliato?

Una cosa che è diversa tra la mia applicazione e l'esempio del Blocco note è che ho iniziato creando la mia applicazione da zero utilizzando la procedura guidata Eclipse mentre l'applicazione di esempio viene già assemblata. C'è una sorta di cambiamento ambientale che devo fare per una nuova applicazione per utilizzare un database SQLite?


Il codice di Tim Wu funziona davvero ...

Se stai usando db.query, sarebbe come questo ...

db.query(TABLE_USER, new String[] { 
                "rowid _id",
                FIELD_USERNAME,
                }, 
                FIELD_USERNAME + "=" + name, 
                null, 
                null, 
                null, 
                null);

Questo probabilmente non è più rilevante, ma ho appena raggiunto lo stesso problema oggi. Risulta che i nomi delle colonne sono case sensitive. Ho avuto una colonna _ID, ma Android si aspetta una colonna _id.


Sì, cambio anche la query stringa SELECT per risolvere questo problema.

String query = "SELECT t.*,t.id as _id FROM table t "; 

Un altro modo per gestire la mancanza di una colonna _id nella tabella è scrivere una sottoclasse di CursorWrapper che aggiunge una colonna _id se necessario.

Questo ha il vantaggio di non richiedere alcuna modifica a tabelle o query.

Ho scritto una lezione del genere e, se è di qualche interesse, può essere trovata su https://github.com/cmgharris/WithIdCursorWrapper


Vedo, la documentazione per CursorAdapter afferma:

Il cursore deve includere una colonna denominata _id o questa classe non funzionerà.

SimpleCursorAdapter è una classe derivata, quindi sembra che questa affermazione si applichi. Tuttavia, la dichiarazione è tecnicamente sbagliata e in qualche modo fuorviante per un principiante. Il set di risultati per il cursore deve contenere _id , non il cursore stesso.
Sono sicuro che questo è chiaro per un DBA perché questo tipo di documentazione di stenografia è chiaro per loro, ma per i neofiti, essere incompleti nella dichiarazione provoca confusione. I cursori sono come iteratori o puntatori, non contengono nient'altro che un meccanismo per il passaggio dei dati, non contengono colonne.

La documentazione di _id contiene un esempio in cui si può vedere che _id è incluso nel parametro di proiezione .

static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
    Contacts._ID,
    Contacts.DISPLAY_NAME,
    Contacts.CONTACT_STATUS,
    Contacts.CONTACT_PRESENCE,
    Contacts.PHOTO_ID,
    Contacts.LOOKUP_KEY,
};
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // ...
    return new CursorLoader(getActivity(), baseUri,
            CONTACTS_SUMMARY_PROJECTION, select, null,
            Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}






sqlite3