如何从自定义数据库助手创建游标
How to create a cursor from a custom database helper
我正在阅读 Griffith 的 Head First:Android 开发 一书,并且某个代码引发了 Cannot resolve Symbol
错误。
我正在按照本书的说明从自定义数据库助手构建游标。这是抛出错误的代码。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink);
int drinkNo = (Integer)getIntent().getExtras().get(EXTRA_DRINKNO);
try{
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
SQLiteDatabase db = starbuzzDatabaseHelper.getReadableDatabase();
它说 Cannot resolve symbol "StarbuzzDatabaseHelper"
尽管 StarbuzzDatabaseHelper 确实存在于我的项目中。这是书中的代码。不是我的。我假设这是书中的错误。我试过这个:
SQLiteOpenHelper starbuzzDatabaseHelper = new SQLiteOpenHelper(this);
还是不行。
这是我的完整代码:
public class DrinkActivity extends AppCompatActivity {
public static final String EXTRA_DRINKNO = "drinkNo";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink);
int drinkNo = (Integer)getIntent().getExtras().get(EXTRA_DRINKNO);
try{
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
SQLiteDatabase db = starbuzzDatabaseHelper.getReadableDatabase();
Cursor cursor = db.query(
"DRINK",
new String[]{"NAME", "DESCRIPTION", "IMAGE_RESOURCE_ID"},
"_id = ?",
new String[]{Integer.toString(drinkNo)},
null, null, null);
if(cursor.moveToFirst()){
String nameText = cursor.getString(0);
String descriptionText = cursor.getString(1);
int photoId = cursor.getInt(2);
TextView name = findViewById(R.id.name);
name.setText(nameText);
TextView description = findViewById(R.id.description);
description.setText(descriptionText);
ImageView photo = findViewById(R.id.photo);
photo.setImageResource(photoId);
photo.setContentDescription(nameText);
}
cursor.close();
db.close();
}catch(SQLiteException e){
Toast.makeText(this, "Database Unavailable", Toast.LENGTH_SHORT).show();
}
}
}
这是数据库助手 class:
public class StarbuzzDatabaseHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "starbuzz";
public static final int DB_VERSION = 2;
public StarbuzzDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, DB_NAME, factory, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
updateMyDatabase(db, 0, DB_VERSION);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
updateMyDatabase(db, oldVersion, newVersion);
}
private void updateMyDatabase(SQLiteDatabase db, int oldVersion, int newVersion){
if(oldVersion <1){
db.execSQL("CREATE TABLE DRINK ("
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "NAME TEXT, "
+ "DESCRIPTION TEXT, "
+ "IMAGE_RESOURCE_ID INTEGER);");
insertDrink(db, "Latte", "Espresso and Steamed Milk", R.drawable.latte);
insertDrink(db, "Capuccino", "Espresso, hot milk and steamed milk foam", R.drawable.cappuccino);
insertDrink(db, "filter", "Our best drink coffee", R.drawable.filter);
}
else if(oldVersion < 2){
db.execSQL("ALTER TABLE DRINK ADD COLUMN FAVORITE NUMERIC");
}
}
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_D", resourceID);
db.insert("DRINK", null, drinkValues);
}
}
而不是
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
尝试
StarbuzzDatabaseHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
编辑:
将其添加到您的助手 class
public StarbuzzDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
您已经定义了 starbuzzDatabaseHelper class 的构造函数,需要 4 个参数:-
public StarbuzzDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, DB_NAME, factory, DB_VERSION);
}
尝试实例化您正在使用的实例:-
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
当您 could/should 使用 :-
StarbuzzDatabaseHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(
this,StarbuzzDatabaseHelper.DBNAME,
your_factory,
StarbuzzDatabaseHelper.DB_VERSION
);
- 即传递 4 个参数(见下文)
- 实例化(创建一个实例)您的数据库助手,而不是受 SQLiteOpenHelper 实例限制的实例。
- 提供可以解决的方法
我建议您将构造函数更改为:-
public StarbuzzDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
因此需要 1 个参数(上下文)
然后在您的 activity(活动)中使用以下内容:-
StarbuzzDatabaseHelper starbuzzDatabaseHelper; //<<<< Class Scope for DBHelper
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink);
int drinkNo = (Integer)getIntent().getExtras().get(EXTRA_DRINKNO);
//<<<< try/catch can be confusing as exceptions may not stop when you very likely should.
starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
SQLiteDatabase db = starbuzzDatabaseHelper.getReadableDatabase();
...... rest of your code
另一个问题
您还有一个问题,您的 insertDrink
方法由于打字错误而无法插入饮料。
即创建 table 时的列是 IMAGE_RESOURCE_ID INTEGER
,但在插入中调用列 IMAGE_RESOURCE_D
。我强烈建议对 table 和列名采用单一来源 (CONSTANTS),并尽可能始终使用它们。
我建议对您的 StarbuzzDatabaseHelper 进行以下更改 class 这应该 remedy/simplify 很重要 :-
public class StarbuzzDatabaseHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "starbuzz";
public static final int DB_VERSION = 2;
public static final String TB_DRINK = "DRINK";
public static final String COL_DRINK_ID = BaseColumns._ID;
public static final String COL_DRINK_NAME = "NAME";
public static final String COL_DRINK_DESCRIPTION = "DESCRIPTION";
public static final String COL_DRINK_IMAGERESOURCEID = "IMAGE_RESOURCE_ID";
public static final String COL_DRINK_FAVOURITE = "FAVOURITE";
public StarbuzzDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
updateMyDatabase(db, 0, DB_VERSION);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
updateMyDatabase(db, oldVersion, newVersion);
}
private void updateMyDatabase(SQLiteDatabase db, int oldVersion, int newVersion){
if(oldVersion <1){
db.execSQL("CREATE TABLE DRINK ("
+ COL_DRINK_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ COL_DRINK_NAME + " TEXT, "
+ COL_DRINK_DESCRIPTION + " TEXT, "
+ COL_DRINK_IMAGERESOURCEID + " INTEGER);");
insertDrink(db, "Latte", "Espresso and Steamed Milk", 1);
insertDrink(db, "Capuccino", "Espresso, hot milk and steamed milk foam", 2);
insertDrink(db, "filter", "Our best drink coffee", 3);
}
else if(oldVersion < 2){
db.execSQL("ALTER TABLE DRINK ADD COLUMN FAVORITE NUMERIC"); //<<< rather then null
}
}
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_D", resourceID); //<<< NO SUCH COLUMN
drinkValues.put(COL_DRINK_IMAGERESOURCEID,resourceID); // NO SPELLING ISSUES this way
db.insert("DRINK", null, drinkValues);
}
// Alternative insert publicly available so activities can add drinks
public long insertDrink(String drink_name,
String drink_description,
int resource_id,
double drink_favourite) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(COL_DRINK_NAME, drink_name);
cv.put(COL_DRINK_DESCRIPTION, drink_description);
cv.put(COL_DRINK_IMAGERESOURCEID,resource_id);
cv.put(COL_DRINK_FAVOURITE,drink_favourite);
return db.insert(TB_DRINK,null,cv);
}
// method to return a Cursor with a sinhle drink as per the id
public Cursor getDrinkById(long id) {
String whereclause = COL_DRINK_ID + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
SQLiteDatabase db = this.getWritableDatabase();
return db.query(TB_DRINK,
null,
whereclause,
whereargs,
null,
null,
null
);
}
// method to return All drinks as a cursor sort according to drink name
public Cursor getAllDrinks() {
return this.getWritableDatabase().query(
TB_DRINK,
null,
null,
null,
null,
null,
COL_DRINK_NAME + " ASC"
);
}
}
以下代码已用于测试上述内容,也是如何利用 class 的示例:-
public class DrinkActivity extends AppCompatActivity {
StarbuzzDatabaseHelper starbuzzDatabaseHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //<<<< change to your layout
starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
Cursor csr = starbuzzDatabaseHelper.getDrinkById(1); //<<< using 1 for testing
if (csr.moveToFirst()) {
Log.d("CURSORINFO","Drink name is " + csr.getString(csr.getColumnIndex(StarbuzzDatabaseHelper.COL_DRINK_NAME)));
//<<<< replace the line above with your code >>>>
}
}
}
备注
- 由于插入导致您的数据库不太可能有任何数据,因此我建议删除数据库。这可以通过 clearing/delete 应用程序的数据或卸载应用程序来完成。
我正在阅读 Griffith 的 Head First:Android 开发 一书,并且某个代码引发了 Cannot resolve Symbol
错误。
我正在按照本书的说明从自定义数据库助手构建游标。这是抛出错误的代码。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink);
int drinkNo = (Integer)getIntent().getExtras().get(EXTRA_DRINKNO);
try{
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
SQLiteDatabase db = starbuzzDatabaseHelper.getReadableDatabase();
它说 Cannot resolve symbol "StarbuzzDatabaseHelper"
尽管 StarbuzzDatabaseHelper 确实存在于我的项目中。这是书中的代码。不是我的。我假设这是书中的错误。我试过这个:
SQLiteOpenHelper starbuzzDatabaseHelper = new SQLiteOpenHelper(this);
还是不行。
这是我的完整代码:
public class DrinkActivity extends AppCompatActivity {
public static final String EXTRA_DRINKNO = "drinkNo";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink);
int drinkNo = (Integer)getIntent().getExtras().get(EXTRA_DRINKNO);
try{
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
SQLiteDatabase db = starbuzzDatabaseHelper.getReadableDatabase();
Cursor cursor = db.query(
"DRINK",
new String[]{"NAME", "DESCRIPTION", "IMAGE_RESOURCE_ID"},
"_id = ?",
new String[]{Integer.toString(drinkNo)},
null, null, null);
if(cursor.moveToFirst()){
String nameText = cursor.getString(0);
String descriptionText = cursor.getString(1);
int photoId = cursor.getInt(2);
TextView name = findViewById(R.id.name);
name.setText(nameText);
TextView description = findViewById(R.id.description);
description.setText(descriptionText);
ImageView photo = findViewById(R.id.photo);
photo.setImageResource(photoId);
photo.setContentDescription(nameText);
}
cursor.close();
db.close();
}catch(SQLiteException e){
Toast.makeText(this, "Database Unavailable", Toast.LENGTH_SHORT).show();
}
}
}
这是数据库助手 class:
public class StarbuzzDatabaseHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "starbuzz";
public static final int DB_VERSION = 2;
public StarbuzzDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, DB_NAME, factory, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
updateMyDatabase(db, 0, DB_VERSION);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
updateMyDatabase(db, oldVersion, newVersion);
}
private void updateMyDatabase(SQLiteDatabase db, int oldVersion, int newVersion){
if(oldVersion <1){
db.execSQL("CREATE TABLE DRINK ("
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "NAME TEXT, "
+ "DESCRIPTION TEXT, "
+ "IMAGE_RESOURCE_ID INTEGER);");
insertDrink(db, "Latte", "Espresso and Steamed Milk", R.drawable.latte);
insertDrink(db, "Capuccino", "Espresso, hot milk and steamed milk foam", R.drawable.cappuccino);
insertDrink(db, "filter", "Our best drink coffee", R.drawable.filter);
}
else if(oldVersion < 2){
db.execSQL("ALTER TABLE DRINK ADD COLUMN FAVORITE NUMERIC");
}
}
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_D", resourceID);
db.insert("DRINK", null, drinkValues);
}
}
而不是
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
尝试
StarbuzzDatabaseHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
编辑: 将其添加到您的助手 class
public StarbuzzDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
您已经定义了 starbuzzDatabaseHelper class 的构造函数,需要 4 个参数:-
public StarbuzzDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, DB_NAME, factory, DB_VERSION);
}
尝试实例化您正在使用的实例:-
SQLiteOpenHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
当您 could/should 使用 :-
StarbuzzDatabaseHelper starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(
this,StarbuzzDatabaseHelper.DBNAME,
your_factory,
StarbuzzDatabaseHelper.DB_VERSION
);
- 即传递 4 个参数(见下文)
- 实例化(创建一个实例)您的数据库助手,而不是受 SQLiteOpenHelper 实例限制的实例。
- 提供可以解决的方法
我建议您将构造函数更改为:-
public StarbuzzDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
因此需要 1 个参数(上下文)
然后在您的 activity(活动)中使用以下内容:-
StarbuzzDatabaseHelper starbuzzDatabaseHelper; //<<<< Class Scope for DBHelper
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drink);
int drinkNo = (Integer)getIntent().getExtras().get(EXTRA_DRINKNO);
//<<<< try/catch can be confusing as exceptions may not stop when you very likely should.
starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
SQLiteDatabase db = starbuzzDatabaseHelper.getReadableDatabase();
...... rest of your code
另一个问题
您还有一个问题,您的 insertDrink
方法由于打字错误而无法插入饮料。
即创建 table 时的列是 IMAGE_RESOURCE_ID INTEGER
,但在插入中调用列 IMAGE_RESOURCE_D
。我强烈建议对 table 和列名采用单一来源 (CONSTANTS),并尽可能始终使用它们。
我建议对您的 StarbuzzDatabaseHelper 进行以下更改 class 这应该 remedy/simplify 很重要 :-
public class StarbuzzDatabaseHelper extends SQLiteOpenHelper {
public static final String DB_NAME = "starbuzz";
public static final int DB_VERSION = 2;
public static final String TB_DRINK = "DRINK";
public static final String COL_DRINK_ID = BaseColumns._ID;
public static final String COL_DRINK_NAME = "NAME";
public static final String COL_DRINK_DESCRIPTION = "DESCRIPTION";
public static final String COL_DRINK_IMAGERESOURCEID = "IMAGE_RESOURCE_ID";
public static final String COL_DRINK_FAVOURITE = "FAVOURITE";
public StarbuzzDatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
updateMyDatabase(db, 0, DB_VERSION);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
updateMyDatabase(db, oldVersion, newVersion);
}
private void updateMyDatabase(SQLiteDatabase db, int oldVersion, int newVersion){
if(oldVersion <1){
db.execSQL("CREATE TABLE DRINK ("
+ COL_DRINK_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ COL_DRINK_NAME + " TEXT, "
+ COL_DRINK_DESCRIPTION + " TEXT, "
+ COL_DRINK_IMAGERESOURCEID + " INTEGER);");
insertDrink(db, "Latte", "Espresso and Steamed Milk", 1);
insertDrink(db, "Capuccino", "Espresso, hot milk and steamed milk foam", 2);
insertDrink(db, "filter", "Our best drink coffee", 3);
}
else if(oldVersion < 2){
db.execSQL("ALTER TABLE DRINK ADD COLUMN FAVORITE NUMERIC"); //<<< rather then null
}
}
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_D", resourceID); //<<< NO SUCH COLUMN
drinkValues.put(COL_DRINK_IMAGERESOURCEID,resourceID); // NO SPELLING ISSUES this way
db.insert("DRINK", null, drinkValues);
}
// Alternative insert publicly available so activities can add drinks
public long insertDrink(String drink_name,
String drink_description,
int resource_id,
double drink_favourite) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cv = new ContentValues();
cv.put(COL_DRINK_NAME, drink_name);
cv.put(COL_DRINK_DESCRIPTION, drink_description);
cv.put(COL_DRINK_IMAGERESOURCEID,resource_id);
cv.put(COL_DRINK_FAVOURITE,drink_favourite);
return db.insert(TB_DRINK,null,cv);
}
// method to return a Cursor with a sinhle drink as per the id
public Cursor getDrinkById(long id) {
String whereclause = COL_DRINK_ID + "=?";
String[] whereargs = new String[]{String.valueOf(id)};
SQLiteDatabase db = this.getWritableDatabase();
return db.query(TB_DRINK,
null,
whereclause,
whereargs,
null,
null,
null
);
}
// method to return All drinks as a cursor sort according to drink name
public Cursor getAllDrinks() {
return this.getWritableDatabase().query(
TB_DRINK,
null,
null,
null,
null,
null,
COL_DRINK_NAME + " ASC"
);
}
}
以下代码已用于测试上述内容,也是如何利用 class 的示例:-
public class DrinkActivity extends AppCompatActivity {
StarbuzzDatabaseHelper starbuzzDatabaseHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //<<<< change to your layout
starbuzzDatabaseHelper = new StarbuzzDatabaseHelper(this);
Cursor csr = starbuzzDatabaseHelper.getDrinkById(1); //<<< using 1 for testing
if (csr.moveToFirst()) {
Log.d("CURSORINFO","Drink name is " + csr.getString(csr.getColumnIndex(StarbuzzDatabaseHelper.COL_DRINK_NAME)));
//<<<< replace the line above with your code >>>>
}
}
}
备注
- 由于插入导致您的数据库不太可能有任何数据,因此我建议删除数据库。这可以通过 clearing/delete 应用程序的数据或卸载应用程序来完成。