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的主要内容,如果未能解决你的问题,请参考以下文章

从数据库中获取列表并在 Listview 中显示需要很长时间

仅包含图像的列表视图

我有一个包含在 ScrollView 中的 ListView 以在标题下显示字符串列表,但无法正确显示

Android 列表视图刷新

使用 listView 和适配器显示对象

Firebase - 显示到 ListView