Android SQLite:尝试重新打开一个已经关闭的对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21058293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android SQLite: attempt to re-open an already-closed object
提问by erad
I'm trying to get certain book data from my Inventory table based on the ISBN.
However, I'm getting an error: "attempt to re-open an already-closed object". The error only occurs when I click a listView object, go to a different screen, go back to this page via "finish()", and then try to click on another listView object. I moved the String searchEntries[] = InventoryAdapter.getInventoryEntriesByISBN(searchQuery, isbn[position]);
from the onClickListener
to the previous for loopbefore the onClickListener
and now it works.
我正在尝试根据 ISBN 从我的 Inventory 表中获取某些书籍数据。但是,我收到一个错误:“尝试重新打开一个已经关闭的对象”。仅当我单击一个 listView 对象,转到另一个屏幕,通过“finish()”返回此页面,然后尝试单击另一个 listView 对象时,才会发生错误。我提出的String searchEntries[] = InventoryAdapter.getInventoryEntriesByISBN(searchQuery, isbn[position]);
从onClickListener
以前的for循环之前onClickListener
和现在的作品。
Why does it not work if I try to getInventoryEntriesByISBN after returning to this activity from another activity via "finish()"?
为什么我在通过“finish()”从另一个活动返回到这个活动后尝试 getInventoryEntriesByISBN 不起作用?
The error occurs at SearchResultsScreen:
错误发生在 SearchResultsScreen:
String searchEntries[] = InventoryAdapter.getInventoryEntriesByISBN(searchQuery, isbn[position]);
and by extension, occurs at InventoryAdapter:
并且通过扩展,发生在 InventoryAdapter:
Cursor cursor = db.rawQuery(query, new String[] {ISBN});
SearchResultsScreen.java
搜索结果屏幕.java
// Set up search array
for(int i = 0; i < isbn.length; i++)
{
searchArray.add(new InventoryItem(isbn[i], InventoryAdapter.getTitleAndAuthorByISBN(isbn[i])));
}
Toast.makeText(getApplicationContext(), "searchArray.size()="+searchArray.size(), Toast.LENGTH_LONG).show();
// add data in custom adapter
adapter = new CustomAdapter(this, R.layout.list, searchArray);
ListView dataList = (ListView) findViewById(R.id.list);
dataList.setAdapter(adapter);
// On Click ========================================================
dataList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
String searchEntries[] = InventoryAdapter.getInventoryEntriesByISBN(searchQuery, isbn[position]);
InventoryAdapter.java (Most relevant parts)
InventoryAdapter.java(最相关的部分)
public String[] getInventoryEntriesByISBN(String search, String ISBN)
{
String[] searchEntry = new String [9];
//Query
String query = "select * from INVENTORY where ISBN = ?";
Cursor cursor = db.rawQuery(query, new String[] {ISBN});
if(cursor.getCount()<1) // title Not Exist
{
cursor.close();
for(int i = 0; i < 9; i++)
searchEntry[i] = "Not Found";
return searchEntry;
}
cursor.moveToFirst();
//put data into respective variable
int publish = cursor.getInt(cursor.getColumnIndex("PUBLISH_DATE"));
String publishdate = ((Integer)publish).toString();
String title = cursor.getString(cursor.getColumnIndex("TITLE"));
String author = cursor.getString(cursor.getColumnIndex("AUTHOR"));
String callNumber = cursor.getString(cursor.getColumnIndex("CALL_NUMBER"));
int available = cursor.getInt(cursor.getColumnIndex("AVAILABLE_COUNT"));
String availablecount = ((Integer)available).toString();
int inventory = cursor.getInt(cursor.getColumnIndex("INVENTORY_COUNT"));
String inventorycount = ((Integer)inventory).toString();
int due = cursor.getInt(cursor.getColumnIndex("DUE_PERIOD"));
String dueperiod = ((Integer)due).toString();
int checkoutcount = cursor.getInt(cursor.getColumnIndex("COUNT"));
String count = ((Integer)checkoutcount).toString();
//combine variables into one array
searchEntry[0] = ISBN;
searchEntry[1] = title;
searchEntry[2] = author;
searchEntry[3] = publishdate;
searchEntry[4] = callNumber;
searchEntry[5] = availablecount;
searchEntry[6] = inventorycount;
searchEntry[7] = dueperiod;
searchEntry[8] = count;
cursor.close();
return searchEntry;
}
public String getTitleAndAuthorByISBN(String ISBN)
{
int entriesFound = getNumSearchEntries(ISBN);
if(entriesFound==0)
entriesFound = 1;
String searchEntry;
//Query
String query = "select * from INVENTORY where ISBN = ?";
Cursor cursor = db.rawQuery(query, new String[] {ISBN});
if(cursor.getCount()<1) // title Not Exist
{
cursor.close();
searchEntry = "Not Found";
return searchEntry;
}
cursor.moveToFirst();
//put data into respective variable
String title = cursor.getString(cursor.getColumnIndex("TITLE"));
String author = cursor.getString(cursor.getColumnIndex("AUTHOR"));
//combine variables into one String
searchEntry = title + " / " + author;
//close cursor and return
cursor.close();
return searchEntry;
}
DataBaseHelper.java
数据库助手
public class DataBaseHelper extends SQLiteOpenHelper
{
// Database Version
private static final int DATABASE_VERSION = 1;
// Database Name
private static final String DATABASE_NAME = "database.db";
// ============================ End Variables ===========================
public DataBaseHelper(Context context, String name, CursorFactory factory, int version)
{
super(context, name, factory, version);
}
public DataBaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Called when no database exists in disk and the helper class needs
// to create a new one.
@Override
public void onCreate(SQLiteDatabase _db)
{
_db.execSQL(LoginDataBaseAdapter.USER_TABLE_CREATE);
_db.execSQL(CheckOutDataBaseAdapter.CHECKOUT_TABLE_CREATE);
_db.execSQL(InventoryAdapter.INVENTORY_TABLE_CREATE);
_db.execSQL(StatisticsAdapter.STATISTICS_TABLE_CREATE);
}
// Called when there is a database version mismatch meaning that the version
// of the database on disk needs to be upgraded to the current version.
@Override
public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion)
{
// Log the version upgrade.
Log.w("TaskDBAdapter", "Upgrading from version " +_oldVersion + " to " +_newVersion + ", which will destroy all old data");
// Upgrade the existing database to conform to the new version. Multiple
// previous versions can be handled by comparing _oldVersion and _newVersion
// values.
// on upgrade drop older tables
_db.execSQL("DROP TABLE IF EXISTS " + LoginDataBaseAdapter.USER_TABLE_CREATE);
_db.execSQL("DROP TABLE IF EXISTS " + CheckOutDataBaseAdapter.CHECKOUT_TABLE_CREATE);
_db.execSQL("DROP TABLE IF EXISTS " + InventoryAdapter.INVENTORY_TABLE_CREATE);
_db.execSQL("DROP TABLE IF EXISTS " + StatisticsAdapter.STATISTICS_TABLE_CREATE);
// Create a new one.
onCreate(_db);
}
}
采纳答案by erad
The error only occurs when I click an item, go to a different screen, go back to this page via "finish()", and then try to click on another listView object.
仅当我单击一个项目,转到另一个屏幕,通过“finish()”返回此页面,然后尝试单击另一个 listView 对象时,才会发生错误。
I moved the String searchEntries[] = InventoryAdapter.getInventoryEntriesByISBN(searchQuery, isbn[position]); from the onClickListener to the previous for loop before the onClickListener and now it works.
我移动了 String searchEntries[] = InventoryAdapter.getInventoryEntriesByISBN(searchQuery, isbn[position]); 从 onClickListener 到 onClickListener 之前的前一个 for 循环,现在它可以工作了。
The correct SearchResultsScreen is below:
正确的 SearchResultsScreen 如下:
SearchResultsScreen.java
搜索结果屏幕.java
// Set up search array
final String Entries[][] = new String[isbn.length][9];
for(int i = 0; i < isbn.length; i++)
{
searchArray.add(new InventoryItem(isbn[i], InventoryAdapter.getTitleAndAuthorByISBN(isbn[i])));
Entries[i] = InventoryAdapter.getInventoryEntriesByISBN(searchQuery, isbn[i]);
}
Toast.makeText(getApplicationContext(), "searchArray.size()="+searchArray.size(), Toast.LENGTH_LONG).show();
// add data in custom adapter
adapter = new CustomAdapter(this, R.layout.list, searchArray);
ListView dataList = (ListView) findViewById(R.id.list);
dataList.setAdapter(adapter);
// On Click ========================================================
dataList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
String searchEntries[] = Entries[position];
回答by Pratik Butani
Check Database Connection before executing query:
在执行查询之前检查数据库连接:
if (!dbHelper.db.isOpen())
dbHelper.open();
if (!dbHelper.db.isOpen())
dbHelper.open();
you can also use cursor.requery();
for again same query.
您也可以cursor.requery();
再次用于相同的查询。
and in last you have to close the cursor and database also.
最后你还必须关闭游标和数据库。
cursor.close();
db.close();
Edited:
编辑:
I have created DBHelper
class which extends SQLiteOpenHelper
, this class is inner class of DatabaseHelper
class and that class have following methods.
我创建了DBHelper
扩展类SQLiteOpenHelper
,这个类是类的内部类,DatabaseHelper
并且该类具有以下方法。
/** For OPEN database **/
public synchronized DatabaseHelper open() throws SQLiteException {
dbHelper = new DBHelper(context);
db = dbHelper.getWritableDatabase();
return this;
}
/** For CLOSE database **/
public void close() {
dbHelper.close();
}
If you have still doubt then feel free to ping me. Thank you.
如果您仍有疑问,请随时 ping 我。谢谢你。
回答by Raghunandan
This is your problem
这是你的问题
if(cursor.getCount()<1) // title Not Exist
{
cursor.close();
for(int i = 0; i < 9; i++)
searchEntry[i] = "Not Found";
return searchEntry;
}
cursor.moveToFirst();
cursor.close();
Change to
改成
for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
{
String title = cursor.getString(cursor.getColumnIndex("TITLE"));
String author = cursor.getString(cursor.getColumnIndex("AUTHOR"));
//combine variables into one String
searchEntry = title + " / " + author;
}
回答by PsyGik
public String[] getInventoryEntriesByISBN(String search, String ISBN)
{
String[] searchEntry = new String [9];
//Query
String query = "select * from INVENTORY where ISBN = ?";
Cursor cursor = db.rawQuery(query, new String[] {ISBN});
Add SQLiteDatabase db = this.getWritableDatabase();
in this code before executing the raw Query
SQLiteDatabase db = this.getWritableDatabase();
在执行原始查询之前添加此代码