Ich habe Probleme mit etwas, das im Notepad-Beispiel funktioniert. Hier ist der Code aus dem 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);
Dieser Code scheint gut zu funktionieren. Um jedoch klar zu sein, habe ich das ADB- Dienstprogramm und SQLite 3 ausgeführt. Ich habe das Schema wie folgt überprüft:
sqlite> .schema
CREATE TABLE android_metadata (locale TEXT);
CREATE TABLE notes (_id integer primary key autoincrement, title text
not null, body text not null);
Alles scheint mir gut zu sein.
Nun zu meiner Bewerbung, die, soweit ich sehen kann, mit ein paar geringfügigen Änderungen im Grunde dieselbe ist. Ich habe meinen Code vereinfacht und vereinfacht, aber das Problem besteht weiterhin.
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);
}
Wenn ich meine Anwendung ausführe, erhalte ich eine RuntimeException und die folgenden Ausdrucke in LogCat aus meiner Log.e()
Anweisung:
LogCat-Nachricht:
java.lang.IllegalArgumentException: Spalte '_id' existiert nicht
Zurück zu SQLite 3, um zu sehen, was an meinem Schema anders ist:
sqlite> .schema CREATE TABLE android_metadata (Gebietsschema TEXT); CREATE TABLE-Kreise (_id Integer-Primärschlüssel-Autoinkrement, Sequenz-Integer, Radius Real, x Real, y Real);
Ich sehe nicht, wie mir die '_id' fehlt.
Was habe ich falsch gemacht?
Eine Sache, die sich zwischen meiner Anwendung und dem Notepad-Beispiel unterscheidet, ist, dass ich meine Anwendung zunächst mit dem Eclipse-Assistenten von Grund auf neu erstellt habe, während die Beispielanwendung bereits zusammengestellt ist. Gibt es eine Art von Umgebungsänderung, die ich vornehmen muss, damit eine neue Anwendung eine SQLite-Datenbank verwendet?
Antworten:
Ich sehe, die Dokumentation für CursorAdapter besagt:
Das
SimpleCursorAdapter
ist eine abgeleitete Klasse, daher scheint diese Aussage zutreffend zu sein. Die Aussage ist jedoch technisch falsch und für einen Neuling etwas irreführend. Die Ergebnismenge für den Cursor muss enthalten_id
, nicht den Cursor selbst.Ich bin sicher, dass dies für einen DBA klar ist, da diese Art von Kurzdokumentation für ihn klar ist, aber für diese Neulinge führt die Unvollständigkeit der Aussage zu Verwirrung. Cursor sind wie Iteratoren oder Zeiger, sie enthalten nichts als einen Mechanismus zum Übertragen der Daten, sie enthalten selbst keine Spalten.
Die Loader-Dokumentation enthält ein Beispiel, in dem ersichtlich ist, dass das
_id
im Projektionsparameter enthalten ist.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"); }
quelle
Dies wurde beantwortet und ich möchte es hier umfassender machen.
SimpleCursorAdapter erfordert, dass die Ergebnismenge des Cursors eine Spalte mit dem genauen Namen "_id" enthält. Beeilen Sie sich nicht, das Schema zu ändern, wenn Sie die Spalte "_id" in Ihrer Tabelle nicht definiert haben. SQLite fügte automatisch eine versteckte Spalte mit dem Namen "rowid" für jede Tabelle hinzu. Alles, was Sie tun müssen, ist, einfach die Zeilen-ID explizit auszuwählen und sie als '_id' zu aliasen.
SQLiteDatabase db = mHelper.getReadableDatabase(); Cursor cur = db.rawQuery( "select rowid _id,* from your_table", null);
quelle
getItemId
meine eigene definierte ID überschreiben und angeben? Kann es das Problem lösen?rowid
Schlüssel erstellt, während sein Standard-Cursoradapter dies erfordert_id
?!Tim Wus Code funktioniert wirklich ...
Wenn Sie db.query verwenden, wäre es so ...
quelle
Ja, ich ändere auch die SELECT-Zeichenfolgenabfrage, um dieses Problem zu beheben.
String query = "SELECT t.*,t.id as _id FROM table t ";
quelle
Was mein Problem mit diesem Fehler löste, war, dass ich die Spalte _id nicht in meine DB-Abfrage aufgenommen hatte. Das Hinzufügen löste mein Problem.
quelle
Das ist wahrscheinlich nicht mehr relevant, aber ich habe heute das gleiche Problem. Es stellt sich heraus, dass Spaltennamen zwischen Groß- und Kleinschreibung unterscheiden. Ich hatte eine _ID-Spalte, aber Android erwartet eine _id-Spalte.
quelle
Wenn Sie die Dokumente auf SQLite lesen und eine Spalte vom Typ INTEGER PRIMARY KEY erstellen, wird die ROWID intern als Alias verwendet. Es lohnt sich also nicht, in jedem SELECT einen Alias hinzuzufügen, der von gängigen Dienstprogrammen abweicht, die möglicherweise die Vorteile von so etwas nutzen eine Aufzählung von Spalten, die die Tabelle definieren.
http://www.sqlite.org/autoinc.html
Es ist auch einfacher, dies als ROWID anstelle der Option AUTOINCREMENT zu verwenden, was dazu führen kann, dass _ID von der ROWID abweichen kann. Wenn Sie _ID mit ROWID verknüpfen, bedeutet dies, dass der Primärschlüssel von insert / insertOrThrow zurückgegeben wird. Wenn Sie einen ContentProvider schreiben, können Sie diesen Schlüssel in der zurückgegebenen Uri verwenden.
quelle
Eine andere Möglichkeit, mit dem Fehlen einer _id-Spalte in der Tabelle umzugehen, besteht darin, eine Unterklasse von CursorWrapper zu schreiben, die bei Bedarf eine _id-Spalte hinzufügt.
Dies hat den Vorteil, dass keine Änderungen an Tabellen oder Abfragen erforderlich sind.
Ich habe eine solche Klasse geschrieben, und wenn sie von Interesse ist, finden Sie sie unter https://github.com/cmgharris/WithIdCursorWrapper
quelle