简体   繁体   中英

Using a SimpleCursorAdapter + Sqlite doesn't seem to work on a ListActivity

I've just started out building a very simple score screen for my app but nothing seems to be happening and I can't figure out why.

The ListActivity:

public class HighScoresActivity extends ListActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.high_scores);

        ScoresDatabase db = new ScoresDatabase(this);
        Cursor data = db.getHighScores();

        ListAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, data, new String[] { "level" }, new int[] { R.id.level_text });
        setListAdapter(adapter);

        data.close();
        db.close();
    }
}

high_scores.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">

    <TextView 
        android:text="Text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/level_text"/>

    <ListView 
        android:id="@android:id/list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

</LinearLayout>

There are no error messages whatsoever, simply nothing happens. Its not that the cursor is blank either, when I test the adapter.getCount() method, it returns ~30, which is exactly as expected.

I think all the function names are pretty much intuitive but if you need any clarification, just ask.

Any help is greatly apprechiated

data.close(); // DON'T DO THIS

From the docs for Cursor.close()...

Closes the Cursor, releasing all of its resources and making it completely invalid. Unlike deactivate() a call to requery() will not make the Cursor valid again.

The Adapter for a ListView has to have a 'live' Cursor otherwise it won't function. Also, closing the database isn't always a good thing and can have adverse effects in certain cases (in my experience) - I'm not sure if that would also be causing a problem though.

EDIT: In light of Dave Newton's comment and having checked some of my own code, the problem will be with calling close() on both the Cursor and also the database. In short, remove the following lines...

data.close();
db.close();

You need to call...

db.open();

at the beginning of onCreate().

This will open your database and allow for data to be retrieved.

The last parameter in the SimpleCursorAdapter ctor should be the ID of the list layout's field, android.R.id.text1 .

The R.id.level_text is the ID of the text field you're using as a header; its text should be set from a string resource, either in the layout file, or dynamically in the onCreate method if you're reusing that layout.

There was 2 problems with my first code.

The first is as MisterSquonk pointed out, prematurely close the cursor and the database.

The second was in correctly binding the data to the views.

Here is the code of my now working solution

HighScoresActivity:

public class HighScoresActivity extends ListActivity {

    private Cursor data;
    private ScoresDatabase db;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.high_scores);

        db = new ScoresDatabase(this);
        data = db.getHighScores();

        ListAdapter adapter = new SimpleCursorAdapter(
                this, 
                R.layout.high_scores_entry, data, 
                new String[] { "level", "moves" }, 
                new int[] { R.id.level_entry, 
                R.id.moves_entry });

        setListAdapter(adapter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        data.close();
        db.close();
    }
} 

high_scores.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >
    <ListView
        android:id="@android:id/android:list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

high_scores_entry.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
    <TextView
        android:id="@+id/level_entry"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <TextView
        android:id="@+id/moves_entry"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

The way I had the data originally bound made no sense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM