我将SQLite数据库用于关于不同面条的项目。对于项目,我使用导航抽屉并从数据库中调用数据。不知何故,当我尝试查询数据时,抛出SQLiteException
并且没有任何反应。
为什么它不起作用?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_noodle);
//set up toolbar as the normal app bar
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
SQLiteOpenHelper databaseHelper = new DatabaseHelper(this);
ListView noodleListPerCategory = findViewById(R.id.selected_noodleList);
try {
database = databaseHelper.getReadableDatabase();
fetch();
//create the cursor adapter to fill the list view with values from the database
SimpleCursorAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor, new String[]{"NAME"},
new int[]{android.R.id.text1}, 0);
noodleListPerCategory.setAdapter(listAdapter);
} catch (SQLiteException e) {
Toast toast = Toast.makeText(this, "Database is not working!", Toast.LENGTH_SHORT);
toast.show();
}
//show item detail using the listener when an item is clicked
AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> noodleListPerCategory, View view, int position, long id) {
//starts DetailActivity
Intent intent = new Intent(NoodleActivity.this, DetailActivity.class);
intent.putExtra(DetailActivity.CHOSEN_NOODLE_ITEM, (int) id);
startActivity(intent);
}
};
//connects the listener to the list view
noodleListPerCategory.setOnItemClickListener(itemClickListener);
}
@Override
public void onDestroy(){
super.onDestroy();
cursor.close();
database.close();
}
public Cursor fetch() {
cursor = this.database.query("NOODLE", new String[]{"_id", "NAME"}, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
答案 0 :(得分:0)
根据此问题和您之前的问题创建了测试。问题主要出在数据库帮助程序类DatabaseHelper
;
在关闭数据库的 addNoodle
方法中,这会导致数据库按以下方式关闭: -
11-07 12:59:35.188 2986-2986/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: mjt.noodle, PID: 2986
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.noodle/mjt.noodle.Noodle}: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/mjt.noodle/databases/NoodleDB
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/mjt.noodle/databases/NoodleDB
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:520)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:262)
at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
at mjt.noodle.Noodle.onCreate(Noodle.java:35)
注意!因为我做了修改以简化测试,所以行号不匹配。 (即显示日志可以让您对问题有所了解)
移除 db.close();
中的 addNoodle
,然后删除应用<&strong数据或(卸载应用程序)将解决此问题。
理所当然,你也应该替换
SQLiteOpenHelper databaseHelper = new DatabaseHelper(this);
的 Databasehelper databaseHelper = new DatabaseHelper(this);
强>
因为你真的想要一个DatabaseHelper对象而不是一个SQLiteOpenHelper对象。但是,这在现阶段没有引起问题,但后来可能会引起混淆或导致问题。
为了测试这个,我使用了以下内容: -
public class Noodle extends AppCompatActivity {
private Cursor cursor;
private SQLiteDatabase database;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_noodle);
//set up toolbar as the normal app bar
//Toolbar toolbar = findViewById(R.id.toolbar);
//setSupportActionBar(toolbar);
DatabaseHelper databaseHelper = new DatabaseHelper(this);
ListView noodleListPerCategory = findViewById(R.id.selected_noodleList);
try {
database = databaseHelper.getReadableDatabase();
fetch();
//create the cursor adapter to fill the list view with values from the database
SimpleCursorAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor, new String[]{"NAME"},
new int[]{android.R.id.text1}, 0);
noodleListPerCategory.setAdapter(listAdapter);
} catch (SQLiteException e) {
Toast toast = Toast.makeText(this, "Database is not working!", Toast.LENGTH_SHORT);
toast.show();
}
//show item detail using the listener when an item is clicked
AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> noodleListPerCategory, View view, int position, long id) {
//starts DetailActivity
/*
Intent intent = new Intent(NoodleActivity.this, DetailActivity.class);
intent.putExtra(DetailActivity.CHOSEN_NOODLE_ITEM, (int) id);
startActivity(intent);
*/
}
};
//connects the listener to the list view
noodleListPerCategory.setOnItemClickListener(itemClickListener);
}
@Override
public void onDestroy(){
super.onDestroy();
cursor.close();
database.close();
}
public Cursor fetch() {
cursor = this.database.query("NOODLE", new String[]{"_id", "NAME"}, null, null, null, null, null);
if (cursor != null) {
cursor.moveToFirst();
}
return cursor;
}
}
与
一起public class DatabaseHelper extends SQLiteOpenHelper {
//the name for the database
private static final String DATABASENAME = "NoodleDB";
//the initial version of the database
private static final int DATABASEVERSION = 1;
private Noodle noodle;
//SQLiteDatabase db;
DatabaseHelper(Context context) {
super(context, DATABASENAME, null, DATABASEVERSION);
//db = this.getReadableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
updateDatabase(db, 0, DATABASEVERSION);
}
/**
* this method updates the database if the db helper's version number is higher than the version number on the db.
*
* @param db The SQLite database
* @param currentVersion The user's version number of the database
* @param updatedVersion The new version of the database written in the helper's code
*/
@Override
public void onUpgrade(SQLiteDatabase db, int currentVersion, int updatedVersion) {
updateDatabase(db, currentVersion, updatedVersion);
}
/**
* This method is called when you want to set the database back to its previous version
*
* @param db The SQLite database
* @param currentVersion The user's version number of the database
* @param updatedVersion The new version of the database written in the helper's code
*/
public void onDowngrade(SQLiteDatabase db, int currentVersion, int updatedVersion) {
}
/**
* This method is for adding new noodle dish to the database
*/
private void addNoodle(SQLiteDatabase db, String name, String description, int imageid, String restaurant) {
ContentValues noodleValues = new ContentValues();
noodleValues.put("NAME", name);
noodleValues.put("DESCRIPTION", description);
noodleValues.put("IMAGEID", imageid);
noodleValues.put("RESTAURANT", restaurant);
db.insert("NOODLE", null, noodleValues);
//db.close();
}
private void updateDatabase(SQLiteDatabase db, int currentVersion, int updatedVersion) {
if(currentVersion >= 1 || currentVersion < 1 ) {
//execute SQL on the db and create a new NOODLE table
db.execSQL("CREATE TABLE NOODLE ("
+ "_id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "NAME TEXT, "
+ "DESCRIPTION TEXT, "
+ "IMAGEID INTEGER, "
+ "RESTAURANT TEXT, "
+ "FAVORITE NUMERIC, "
+ "CATEGORY TEXT);");
addNoodle(db,"Spicy Ramen", "Chicken broth, marinated pork, chilli and bean sprouts", 1, "Totemo");
addNoodle(db,"Tokyo Ramen", "Dashi-based broth, marinated pork and fermented bamboo shoots", 2, "Totemo");
addNoodle(db,"Vegetarian Ramen", "Mushroom dashi-based broth, tofu, pak choi, miso and corn", 3, "Ramen Manga");
addNoodle(db,"Miso Ramen", "Miso broth, marinated pork, egg, spring onion and bean sprouts", 4, "Cafe Steigman");
addNoodle(db,"Tonkatsu Ramen", "Pork bone based broth, grilled pork, spicy garlic with miso", 5, "Blue Light Yokohama");
addNoodle(db,"Shio Ramen", "Seasalt broth, pork, egg, quail and vegetable", 6, "Ai Ramen");
addNoodle(db,"Nabeyaki Udon", "Udon noodles in fish broth with chicken, shrimp, egg and leek", 7, "Ki-mama Ramen");
}
if(currentVersion <=2) {
}
}
}
,虽然相当无关
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="mjt.noodle.Noodle">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
<ListView
android:id="@+id/selected_noodleList"
android:layout_width="match_parent"
android:layout_height="wrap_content"></ListView>
</LinearLayout>
以上导致: -