3 Stimmen

Fehlersuche im SimpleCursorAdapter

Ich arbeite an meiner ersten Android-App und kann nicht herausfinden, wie ich meine SimpleCursorAdpater um die Ansicht zu füllen. Der Cursor, den ich in übergeben hat Ergebnisse in es, so dass das Problem irgendwo in der Instanziierung des Adapters oder in der Bindung es an die Ansicht sein muss. Ich bin irgendwie am Ende meiner Weisheit, da keine Ausnahmen ausgelöst werden und ich kann nicht wirklich Schritt in setListAdapter.

So bekomme ich meinen Cursor überhaupt erst:

    Searches searches = new Searches(this);

    SQLiteDatabase db = searches.getReadableDatabase();
    //select _id, Name, Search FROM Searches;
    Cursor c = db.query(
                SearchConstants.TABLE_NAME, 
                FROM, null, null, null, 
                null, null);
    startManagingCursor(c);

Und das ist das Schema für meine Datenbank:

CREATE TABLE Searches (_id INTEGER PRIMARY KEY, Name Text, Search TEXT)

Hier sind die beiden Zeilen, in denen die Dinge beginnen, auseinanderzufallen:

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.search, cursor, FROM, TO);
setListAdapter(adapter);

Mein Hauptlayout sieht wie folgt aus:

<ListView
    android:id="@android:id/android:list"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
<TextView
    android:id="@android:id/android:empty"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/empty" />

Hier ist die Ansicht, die mit jedem Ergebnis zu füllen ist:

<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:orientation="horizontal"
  android:padding="10sp">
  <TextView
    android:id="@+id/_id"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
  <TextView
    android:id="@+id/name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
  <TextView
    android:id="@+id/colon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text=": "
    android:layout_toRightOf="@id/name" />
  <TextView
    android:id="@+id/search"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:ellipsize="end"
    android:singleLine="true"
    android:textStyle="italic"
    android:layout_toRightOf="@id/colon" />
</RelativeLayout>

Schließlich sind hier die statischen Variablen, die ich verwendet habe:

//search query stuff
private static String[] FROM = {SearchConstants._ID, SearchConstants.NAME_COLUMN, SearchConstants.SEARCH_COLUMN};

//where to paste search results
private static int[] TO = {R.id._id, R.id.name, R.id.search};

/**
 * Table name
 */
public static final String TABLE_NAME = "Searches";

/**
 * Name Column
 */
public static final String NAME_COLUMN = "Name";

/**
 * Search Column
 */
public static final String SEARCH_COLUMN = "Search";

Ich denke, das ist der gesamte relevante Code. Ich habe keine Ahnung, wie man an dieser Stelle fortfahren, so dass alle Vorschläge überhaupt hilfreich sein würde.

Danke! Brian

PS: Sieht so aus, als gäbe es hier eine Menge toller Vorschläge - ich ignoriere sie nicht, ich hatte nur noch nicht die Gelegenheit dazu. Danke für die Ratschläge! Irgendwann werde ich sie alle durchgehen und versuchen, ein Feedback dazu zu geben, welche Dinge für mich gut funktioniert haben.

3voto

kichik Punkte 30440

Sie können in den Code einsteigen, wenn Sie den Quellcode haben. Glücklicherweise ist Android quelloffen. Wie Sie den Quellcode in Eclipse anhängen können, erfahren Sie hier:

http://Android.opensourceror.org/2010/01/18/Android-source/

Was das Problem selbst betrifft, sagten Sie in einem Kommentar oben, dass Sie alle Elemente iterieren, bevor Sie den Adapter erstellen. Wenn Sie keinen neuen Cursor nach der Iteration erstellen, müssen Sie ihn wahrscheinlich zurückspulen oder der Adapter könnte denken, dass er leer ist.

cursor.moveToFirst()

2voto

cody Punkte 5969

Bitte machen Sie sich keine Sorgen über interne Bindungsaspekte. Ich bin sicher, dass es einen einfachen Ausweg gibt. Versuchen Sie das Folgende: Erstens, um sicherzustellen, dass Ihr Cursor die Daten auch wirklich dorthin bekommt, wo sie gebraucht werden, fügen Sie die Zeile

System.out.println("cursor.getCount()="+cursor.getCount());

direkt vor dem Aufruf von setAdapter(). Aber sicher haben Sie bereits getestet, um eine Zeilenzahl zu erhalten ;-) Das Folgende könnte also interessanter sein.

Um zu prüfen, ob Ihre Bindung fehlschlägt, testen Sie bitte mit:

android:id="@+id/android:list"

anstelle von:

android:id="@android:id/android:list"

in Ihrer main.xml. Dasselbe gilt für: Android:id="@+id/Android:empty".

Und wenn Sie immer noch keine Ergebnisse erhalten, können Sie auch versuchen, eine Liste Standard-xml-Layout (wie simple_list_item_1) für die Anzeige zu verwenden, die wie folgt aussehen würde:

ListAdapter adapter = new SimpleCursorAdapter(this, 
    // Use a template that displays a text view
    android.R.layout.simple_list_item_1, 
    // Give the cursor to the list adapter
    cursor, 
    // Map the NAME column in your database to...
    new String[] {SearchConstants.NAME_COLUMN} ,
    // ...the "text1" view defined in the R.layout.simple_list_item_1
    new int[] {android.R.id.text1}
);

Kopieren Sie es einfach in Ihre Aktivität und sehen Sie, was passiert. Ich hoffe, Sie sind damit fertig!

1voto

Jesus Army Punkte 11

Ich habe gerade das gleiche Problem und habe herausgefunden, wie man die Simplecursoradapter-Erstellung nicht fehlschlagen lässt.

In Ihrem Cursor MUSS die Abfrage der Datenbank den Primärschlüssel der Tabelle enthalten, auch wenn Sie ihn nicht benötigen! Wenn nicht, wird sie fehlschlagen und abstürzen...

Ich hoffe, es hilft anderen, die das gleiche Problem haben!

0voto

cody Punkte 5969

Mir ist aufgefallen, dass Sie einen Spaltennamen mit einem Großbuchstaben verwendet haben. Vergewissern Sie sich, dass Sie den genauen Bezeichner im DB-Schema verwenden (bei den Sqlite-Spaltennamen wird zwischen Groß- und Kleinschreibung unterschieden). Aber in dem von Ihnen angegebenen Code stimmen die Spaltenbezeichner überein.

Wenn der von Ihnen verwendete Cursor also wirklich die Daten hat, probieren Sie zunächst den obigen Code aus (anstelle eines benutzerdefinierten Layouts), um einen SimpleCursorAdapter zu erstellen, und es sollte funktionieren. Hier ist ein weiteres kleines Beispiel für den Aktivitätscode (da ich Ihren nicht kenne):

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.dbManager = new DatabaseManager(this);

    setContentView(R.layout.main);
    registerForContextMenu(getListView()); // catch clicks

    if (!showList()) {
        TextView tv = new TextView(this);
        tv.setText(getString(R.string.txt_list_empty));
        setContentView(tv);
    }
}

private boolean showList() {
    final Cursor c = dbManager.fetchListData();
    startManagingCursor(c); // when the Activity finishes, the cursor is closed

    if (!c.moveToFirst())
        return false;

    final SimpleCursorAdapter myAdapter = new SimpleCursorAdapter(
            this, android.R.layout.simple_list_item_2, c,
            new String[]{"name"} , new int[]{android.R.id.text1} );

    setListAdapter(myAdapter);
    return true;
}

Bevor Sie viel Zeit dort verbringen, wo Sie auf Probleme stoßen, fangen Sie lieber dort an, wo die Dinge noch funktionieren, und machen Sie kleine Schritte für Erweiterungen. Wenn man sie einfach hält, gibt es keine große Magie bei der Verwendung von Adaptern.

0voto

aprock Punkte 1602

Sie könnten versuchen, einen ViewBinder für die Fehlersuche einzufügen. Sie können damit überprüfen, welche Werte für welche Ansichten im SimpleCursorAdaptor übergeben werden. Oder verwenden Sie es einfach, um die Bindung manuell selbst zu tun.

So etwas sollte funktionieren:

adapter.setViewBinder(new SimpleCursorBinder());

y luego

public class SimpleCursorBinder implements SimpleCursorAdpater.ViewBinder {
    public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
        /* set breakpoints and examine incoming data. */
        // returning false, causes SimpleCursorAdapter to handing the binding
        boolean bound = false;

        String columnName = cursor.getColumnName(columnIndex);
        TextView bindingView = null;
        int viewId = view.getId();

        // could just use this opportunity to manually bind
        if (columnName.equals(SearchConstants._ID)) {
            bindingView = (TextView)(viewId == R.id._id ? view : null);
        } else if (columnName.equals(SearchConstants.NAME_COLUMN)) {
            bindingView = (TextView)(viewId == R.id.name ? view : null);
        } else if (columnName.equals(SearchConstants.SEARCH_COLUMN)) {
            bindingView = (TextView)(viewId == R.id.search ? view : null);
        }

        if (bindingView != null) {
            bindingView.setText(cursor.getString(columnIndex));
            bound = true;
        }

        return bound;
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X