ListView 没有向我显示包含数据库名称的列表。我使用 SimpleCursorAdapter

Posted

技术标签:

【中文标题】ListView 没有向我显示包含数据库名称的列表。我使用 SimpleCursorAdapter【英文标题】:The ListView doesn't show me a list with names from database. I use SimpleCursorAdapter 【发布时间】:2021-09-28 03:18:47 【问题描述】:

我正在尝试为我的应用程序实现数据库。这是我第一次这样做。 我有一个带有列表视图的布局,我使用 SimpleCoursorAdapter 将数据从数据库传输到我的 ListView。该应用程序没有显示任何内容。 ListView 是空的,我不知道为什么。

这是我的 TopLevelActivity

public class TopLevelActivity extends Activity 

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

        AdapterView.OnItemClickListener itemClickListener =
                                                    new AdapterView.OnItemClickListener() 
                    @Override
                    public void onItemClick(AdapterView<?> listView,
                                            View v,
                                            int position,
                                            long id) 
                        if(position == 0)
                            Intent intent = new Intent(TopLevelActivity.this, DrinkCategoryActivity.class);
                            startActivity(intent);
                        
                        if(position == 1)
                            Intent intent = new Intent(TopLevelActivity.this, SnacksCategoryActivity.class);
                            startActivity(intent);
                        

                    
                ;
        ListView listView = (ListView) findViewById(R.id.list_options);
        listView.setOnItemClickListener(itemClickListener);
    

来自TopLevelActivity的xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    android:orientation="vertical"
    tools:context=".TopLevelActivity">

    <ImageView
        android:layout_
        android:layout_
        android:src="@drawable/starbuzz_logo"
        android:contentDescription="@string/starbuzz_logo"/>

    <ListView
        android:id="@+id/list_options"
        android:layout_
        android:layout_
        android:entries="@array/options"/>


</LinearLayout>

我认为这里的 DrinkCategoryActivity 有些错误

public class DrinkCategoryActivity extends Activity 
    private SQLiteDatabase db;
    private Cursor cursor;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drink_category);
        ListView listDrinks = (ListView) findViewById(R.id.list_drinks);

        SQLiteOpenHelper coffeinaDatabaseHelper = new CoffeinaDatabaseHelper(this);
        try 
            db = coffeinaDatabaseHelper.getReadableDatabase();
            cursor = db.query("DRINK",
                    new String[]"_id", "NAME",
                    null, null, null, null, null);

            SimpleCursorAdapter listAdapter = new SimpleCursorAdapter
                    (this,
                            android.R.layout.simple_list_item_1,
                            cursor,
                            new String[]"NAME",
                            new int[]android.R.id.text1,0
                            );
            listDrinks.setAdapter(listAdapter);
         catch (SQLiteException e) 
            Toast toast = Toast.makeText(this, "Baza danych jest niedostepna",
                    Toast.LENGTH_SHORT);
            toast.show();

        



    AdapterView.OnItemClickListener itemClickListener =
            new AdapterView.OnItemClickListener() 
                public void onItemClick(AdapterView<?> listDrinks,
                                        View itemView,
                                        int position,
                                        long id) 
                    Intent intent = new Intent(DrinkCategoryActivity.this,
                            DrinkActivity.class);
                    intent.putExtra(DrinkActivity.EXTRA_DRINKID, (int) id);
                    startActivity(intent);
                
            ;

        listDrinks.setOnItemClickListener(itemClickListener);



    public void onDestroy() 
        super.onDestroy();
        cursor.close();
        db.close();
    

来自 DrinkCategoryActivity 的xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:orientation="vertical"
    android:layout_
    tools:context=".DrinkCategoryActivity">

    <ListView
        android:id="@+id/list_drinks"
        android:layout_
        android:layout_/>





</LinearLayout>

饮酒活动

public class DrinkActivity extends AppCompatActivity 

    public static final String EXTRA_DRINKID = "drinkId";





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

        int drinkId = (Integer)getIntent().getExtras().get(EXTRA_DRINKID);
        
        SQLiteOpenHelper starbuzzDatabaseHelper = new CoffeinaDatabaseHelper(this);

        try
            SQLiteDatabase db = starbuzzDatabaseHelper.getReadableDatabase();
            Cursor cursor = db.query("DRINK",
                                        new String[]"NAME", "DESCRIPTION", "IMAGE_RESORUCE_ID",
                    "_id = ?",
                    new String[]Integer.toString(drinkId),
                    null, null, null);


            if(cursor.moveToFirst())
                String nameText = cursor.getString(0);
                String descriptionText = cursor.getString(1);
                int photoId = cursor.getInt(2);

                TextView name = (TextView)findViewById(R.id.name);
                name.setText(nameText);

                TextView description = (TextView)findViewById(R.id.description);
                description.setText(descriptionText);

                ImageView photo = (ImageView)findViewById(R.id.latte);
                photo.setImageResource(photoId);
                photo.setContentDescription(nameText);

            
            cursor.close();
            db.close();

        catch (SQLiteException e)
            Toast toast = Toast.makeText(this, "Bada danych jest niedostepna",
                    Toast.LENGTH_SHORT);
            toast.show();
        


    

来自 DrinkActivity 的xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_
    android:layout_
    android:orientation="vertical"
    tools:context=".DrinkActivity">
    
    <ImageView
        android:id="@+id/latte"
        android:layout_
        android:layout_/>
    <TextView
        android:id="@+id/name"
        android:layout_
        android:layout_/>

    <TextView
        android:id="@+id/description"
        android:layout_
        android:layout_/>


</LinearLayout>

我的 DataBaseHelper 和这里也可能有些错误。 复杂器没有显示任何错误。


package com.hfad.coffeina;

import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class CoffeinaDatabaseHelper extends SQLiteOpenHelper 

    private static final String DB_NAME = "coffeina";
    private static final int DB_VERSION = 2;

    CoffeinaDatabaseHelper(Context context)

        super(context, DB_NAME, null, DB_VERSION);
    

    public  void onCreate(SQLiteDatabase db)
        updateMyDatabase(db, 0, DB_VERSION);

    

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
            updateMyDatabase(db, oldVersion, newVersion);
    

    private static void insertDrink(SQLiteDatabase db, String name, String description,
                                       int resourceId)
        ContentValues drinkValues = new ContentValues();
        drinkValues.put("NAME", name);
        drinkValues.put("DESCRIPTION", description);
        drinkValues.put("IMAGE_RESOURCE_ID", resourceId);
        db.insert("DRINK", null, drinkValues);

    

    private void updateMyDatabase(SQLiteDatabase db, int oldVersion, int newVersion)
        if(oldVersion < 1)
            db.execSQL("CREATE TABLE DRINK (_id INTEGER PRIMARY KEY AUTOINCREMENT, "
                    +"NAME TEXT, "
                    +"DESCRIPTON TEXT , "
                    +"IMAGE_RESOURCE_ID INTEGER);");
            insertDrink(db, "Latte", "Czarne espresso z gorącym mlekiem i mleczną pianką.",
                    R.drawable.latte);
            insertDrink(db, "Cappucciono", "Czarne espresso z dużą ilościa spienionego mleka",
                    R.drawable.cappuccino);
            insertDrink(db, "Espresso", "Czarna kawa ze świeżo mielonych ziaren najwyższej jakości.",
                    R.drawable.filter);
        
        if(oldVersion < 2)
            db.execSQL("ALTER TABLE DRINK ADD COLUMN FAVORITE NUMERIC;");
        
    


来自模拟器enter image description here的打印屏幕

【问题讨论】:

【参考方案1】:

问题

我相信您的主要问题是,在 DRINK 表中,您使用 +"DESCRIPTON TEXT , " 定义了列名,但您引用了 DESCRIPTION 列(tion as与吨相反)在其他地方,包括在插入 3 个初始行时。隐藏/伪装,因为它们在 try .... catch 构造中。

请注意,在 try .... catch 中包装 SQLite 内容通常没有帮助并导致混淆,尤其是在测试时未检查日志的情况下。

那是日志会显示类似:-

07-21 17:29:20.748 4340-4340/a.a.so68457788javesqlitelistview E/SQLiteLog: (1) table DRINK has no column named DESCRIPTION
07-21 17:29:20.749 4340-4340/a.a.so68457788javesqlitelistview E/SQLiteDatabase: Error inserting NAME=Latte DESCRIPTION=Czarne espresso z gorącym mlekiem i mleczną pianką. IMAGE_RESOURCE_ID=10
    android.database.sqlite.SQLiteException: table DRINK has no column named DESCRIPTION (code 1): , while compiling: INSERT INTO DRINK(NAME,DESCRIPTION,IMAGE_RESOURCE_ID) VALUES (?,?,?)
        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:887)
        at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:498)
        at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
        at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
        at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
        at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469)
        at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341)
        at a.a.so68457788javesqlitelistview.CoffeinaDatabaseHelper.insertDrink(CoffeinaDatabaseHelper.java:32)
        at a.a.so68457788javesqlitelistview.CoffeinaDatabaseHelper.updateMyDatabase(CoffeinaDatabaseHelper.java:42)
        at a.a.so68457788javesqlitelistview.CoffeinaDatabaseHelper.onCreate(CoffeinaDatabaseHelper.java:18)

因此数据库将是空的,因此 ListView 什么也不显示。

我建议始终对数据库组件使用单一定义,并始终使用单一定义引用组件。

建议的修复/改进

也许考虑使用:-

class CoffeinaDatabaseHelper extends SQLiteOpenHelper 

    private static final String DB_NAME = "coffeina";
    private static final int DB_VERSION = 2;
    public static final String  DRINK_TABLENAME = "DRINK";
    public static final String DRINK_ID_COLUMN = BaseColumns._ID; // Android _id column name
    public static final String DRINK_NAME_COLUMN = "NAME";
    public static final String DRINK_DESCRIPTION_COLUMN = "DESCRIPTION";
    public static final String DRINK_IMAGE_RESOURCE_ID_COLUMN = "IMAGE_RESOURCE_ID";
    public static final String DRINK_FAVORITE_COLUMN = "FAVOURITE";

    CoffeinaDatabaseHelper(Context context)
        super(context, DB_NAME, null, DB_VERSION);
    

    public  void onCreate(SQLiteDatabase db)
        updateMyDatabase(db, 0, DB_VERSION);
    

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
        updateMyDatabase(db, oldVersion, newVersion);
    

    private static void insertDrink(SQLiteDatabase db, String name, String description,
                                    int resourceId)
        ContentValues drinkValues = new ContentValues();
        drinkValues.put(DRINK_NAME_COLUMN, name);
        drinkValues.put(DRINK_DESCRIPTION_COLUMN, description);
        drinkValues.put(DRINK_IMAGE_RESOURCE_ID_COLUMN, resourceId);
        db.insert(DRINK_TABLENAME, null, drinkValues);
    

    private void updateMyDatabase(SQLiteDatabase db, int oldVersion, int newVersion)
        if(oldVersion < 1)
            /* no need for autoincrement id's will be generated without the overheads 
                check https://sqlite.org/autoinc.html for details/why
            */
            db.execSQL("CREATE TABLE " + DRINK_TABLENAME + " (" + DRINK_ID_COLUMN + " INTEGER PRIMARY KEY, "
                    + DRINK_NAME_COLUMN + " TEXT,"
                    + DRINK_DESCRIPTION_COLUMN +" TEXT , "
                    + DRINK_IMAGE_RESOURCE_ID_COLUMN + " INTEGER);");
            insertDrink(db, "Latte", "Czarne espresso z gorącym mlekiem i mleczną pianką.",10);
            insertDrink(db, "Cappucciono", "Czarne espresso z dużą ilościa spienionego mleka", 11);
            insertDrink(db, "Espresso", "Czarna kawa ze świeżo mielonych ziaren najwyższej jakości.", 12);
        
        if(oldVersion < 2)
            db.execSQL("ALTER TABLE DRINK ADD COLUMN " + DRINK_FAVORITE_COLUMN + " NUMERIC;");
        
    

注意用于测试图像资源 id 的已编好,需要更改以反映您的原始代码。

然后随后使用常量在别处引用数据库组件。例如,考虑以下版本的 DrinkCategoryActivity 类:-

public class DrinkCategoryActivity extends AppCompatActivity 

    CoffeinaDatabaseHelper coffeinaDatabaseHelper; //<<<<< ADDED you want instance of YOUR helper not an SQLiteOpenHelper
    SQLiteDatabase db;
    Cursor cursor;
    SimpleCursorAdapter listAdapter; //<<<<< Better here, more scope
    ListView listDrinks;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drink_category);
        listDrinks = (ListView) findViewById(R.id.list_drinks);
        // SQLiteOpenHelper coffeinaDatabaseHelper = new CoffeinaDatabaseHelper(this);
        coffeinaDatabaseHelper = new CoffeinaDatabaseHelper(this);
        db = coffeinaDatabaseHelper.getWritableDatabase(); // get readable will typically get writeable anyway
        setOrRefreshListView();
    

    private void setOrRefreshListView() 
        cursor = db.query(CoffeinaDatabaseHelper.DRINK_TABLENAME,
                new String[]"_id", CoffeinaDatabaseHelper.DRINK_NAME_COLUMN,
                null, null, null, null, null);
        if (listAdapter == null) 
            listAdapter = new SimpleCursorAdapter(
                    this,
                    android.R.layout.simple_list_item_1, cursor,
                    new String[]"NAME",
                    new int[]android.R.id.text1, 0);
            listDrinks.setAdapter(listAdapter);
            listDrinks.setOnItemClickListener(new AdapterView.OnItemClickListener() 
                @Override
                public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) 
                    Intent intent = new Intent(view.getContext(), DrinkActivity.class);
                    intent.putExtra(DrinkActivity.EXTRA_DRINKID, l);
                    startActivity(intent);
                
            );
         else 
            listAdapter.swapCursor(cursor);
        
    

    /* If returning to Activity (from DrinkActivity) refresh the ListView
        just in case it has changed
     */
    @Override
    protected void onResume() 
        super.onResume();
        setOrRefreshListView();
    

    @Override
    protected void onDestroy() 
        super.onDestroy();
        cursor.close();
    

然后使用上面的:-

附加

进一步了解上述内容,DrinkActity 的工作(尽管没有图像)和更简洁的版本是:-

public class DrinkActivity extends AppCompatActivity 

    public static final String EXTRA_DRINKID = "drinkId";
    CoffeinaDatabaseHelper DBHelper;
    SQLiteDatabase db;
    TextView name,description;
    ImageView photo;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drink);
        long drinkId = this.getIntent().getLongExtra(DrinkActivity.EXTRA_DRINKID,-1); // Should be LONG
        DBHelper = new CoffeinaDatabaseHelper(this);
        db = DBHelper.getWritableDatabase();
        name = this.findViewById(R.id.name);
        description = this.findViewById(R.id.description);
        Cursor cursor = db.query(CoffeinaDatabaseHelper.DRINK_TABLENAME,
                null,
                CoffeinaDatabaseHelper.DRINK_ID_COLUMN +" = ?",
                new String[]String.valueOf(drinkId), // cope with Long
                null, null, null);
        if(cursor.moveToFirst())
            name.setText(cursor.getString(cursor.getColumnIndex(CoffeinaDatabaseHelper.DRINK_NAME_COLUMN)));
            description.setText(cursor.getString(cursor.getColumnIndex(CoffeinaDatabaseHelper.DRINK_DESCRIPTION_COLUMN)));
            //<<<<< COMMENTED OUT FOR TESTING (as invalid resource id's have been used) >>>>>
            //photo.setImageResource(cursor.getInt(cursor.getColumnIndex(CoffeinaDatabaseHelper.DRINK_IMAGE_RESOURCE_ID_COLUMN)));
            //photo.setContentDescription(cursor.getString(cursor.getColumnIndex(CoffeinaDatabaseHelper.DRINK_NAME_COLUMN)));
         else 
            Toast.makeText(this, "Bada danych jest niedostepna", Toast.LENGTH_SHORT).show();
        
        cursor.close();
        //db.close(); don't close, resource expensive to open
    

所以选择拿铁咖啡会给出:-

【讨论】:

我检查你的修复版本。首先,我看看你做了什么,我正在实现它,它仍然无法正常工作,而不是我复制你的代码并粘贴到我的 android studio 并且仍然是相同的 Table 是空的并且 ListView 显示 nothink 但是当我检查平板电脑模拟器时比工作在电话上没有,但为什么 @JacobNatural 您可能需要在手机上重新安装。一旦数据库被创建,如果停留在那里,那么 onCreate 就不会再次运行。重新安装会删除数据库。 我无法打开光标。我的 DrinkActivity 不起作用。我复制了您的代码,但仍然没有。我再次从手机安装中删除了应用程序,但仍然没有。 好的,我解决了这个问题。当我创建表时,我有 PRIMARY KEY 而不是 INTEGER PRIMARY KEY

以上是关于ListView 没有向我显示包含数据库名称的列表。我使用 SimpleCursorAdapter的主要内容,如果未能解决你的问题,请参考以下文章