ListView 没有向我显示包含来自数据库的名称的列表。我使用 SimpleCursorAdapter
The ListView doesn't show me a list with names from database. I use SimpleCursorAdapter
我正在尝试为我的应用程序实施数据库。这是我第一次这样做。
我有一个带有列表视图的布局,我使用 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);
}
}
xml 来自 TopLevelActivity
<?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_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".TopLevelActivity">
<ImageView
android:layout_width="200dp"
android:layout_height="100dp"
android:src="@drawable/starbuzz_logo"
android:contentDescription="@string/starbuzz_logo"/>
<ListView
android:id="@+id/list_options"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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();
}
}
xml 来自 DrinkCategoryActivity
<?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_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".DrinkCategoryActivity">
<ListView
android:id="@+id/list_drinks"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
DrinkAtivity
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();
}
}
}
xml 来自 DrinkActivity
<?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_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".DrinkActivity">
<ImageView
android:id="@+id/latte"
android:layout_width="190dp"
android:layout_height="190dp"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</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
问题
我认为您的主要问题是在 DRINK table 中您使用 +"DESCRIPTON TEXT , "
定义了一个列名称,但您引用了 DESCRIPTION 列( tion 而不是 ton) 在其他地方包括插入 3 个初始行时。 Hidden/disguised 因为它们在 try ....catch 构造中。
请注意,将 SQLite 的东西包装在 try...catch 中通常是没有帮助的,并且会导致混淆,尤其是在测试时未检查日志的情况下。
那是日志会显示类似 :-
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 什么也不显示。
我建议始终对数据库组件使用单一定义,并且始终使用单一定义来引用组件。
建议Fix/Improvment
也许考虑使用 :-
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 class :-
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
}
}
所以选择 Latte 会得到:-
我正在尝试为我的应用程序实施数据库。这是我第一次这样做。 我有一个带有列表视图的布局,我使用 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);
}
}
xml 来自 TopLevelActivity
<?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_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".TopLevelActivity">
<ImageView
android:layout_width="200dp"
android:layout_height="100dp"
android:src="@drawable/starbuzz_logo"
android:contentDescription="@string/starbuzz_logo"/>
<ListView
android:id="@+id/list_options"
android:layout_width="match_parent"
android:layout_height="wrap_content"
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();
}
}
xml 来自 DrinkCategoryActivity
<?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_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".DrinkCategoryActivity">
<ListView
android:id="@+id/list_drinks"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
DrinkAtivity
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();
}
}
}
xml 来自 DrinkActivity
<?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_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".DrinkActivity">
<ImageView
android:id="@+id/latte"
android:layout_width="190dp"
android:layout_height="190dp"/>
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</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
问题
我认为您的主要问题是在 DRINK table 中您使用 +"DESCRIPTON TEXT , "
定义了一个列名称,但您引用了 DESCRIPTION 列( tion 而不是 ton) 在其他地方包括插入 3 个初始行时。 Hidden/disguised 因为它们在 try ....catch 构造中。
请注意,将 SQLite 的东西包装在 try...catch 中通常是没有帮助的,并且会导致混淆,尤其是在测试时未检查日志的情况下。
那是日志会显示类似 :-
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 什么也不显示。
我建议始终对数据库组件使用单一定义,并且始终使用单一定义来引用组件。
建议Fix/Improvment
也许考虑使用 :-
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 class :-
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
}
}
所以选择 Latte 会得到:-