Java 正在从Android数据库删除项-光标索引超出范围异常
在我的android应用程序中,我试图从数据库中删除一个项目,在列表视图中选择了相应的项目,并从长按创建的上下文菜单中选择了一个项目。listview是从arraylist填充的,arraylist是从数据库中的项创建的 但是,我在尝试删除listview中除第一项以外的任何内容时出错(这实际上是最近添加的项,也是arraylist中的最后一项,因为listview以相反的顺序显示列表中的项)。如果我尝试删除除最新项目以外的项目,则会出现一个错误,android.database.CursorIndexOutOfBoundsException:请求索引0,大小为0 在这个错误之后,如果我试图打开包含listview的活动,我也会收到相同的错误,直到我删除应用程序的数据并再次打开它 如果光标为空并且正在移动到下一行,我尝试了在databasehandler deleteGoalFromDb方法中进行检查,但到目前为止没有成功 在上下文菜单中按delete项时调用的方法(它是菜单中唯一的项): My deleteGoal()方法: deleteGoalFromDb:Java 正在从Android数据库删除项-光标索引超出范围异常,java,android,android-listview,android-sqlite,android-cursor,Java,Android,Android Listview,Android Sqlite,Android Cursor,在我的android应用程序中,我试图从数据库中删除一个项目,在列表视图中选择了相应的项目,并从长按创建的上下文菜单中选择了一个项目。listview是从arraylist填充的,arraylist是从数据库中的项创建的 但是,我在尝试删除listview中除第一项以外的任何内容时出错(这实际上是最近添加的项,也是arraylist中的最后一项,因为listview以相反的顺序显示列表中的项)。如果我尝试删除除最新项目以外的项目,则会出现一个错误,android.database.CursorI
public void deleteGoalFromDb(int id){
SQLiteDatabase db = this.getWritableDatabase();
db.delete(TABLE_GOALS, KEY_ID + " = ?", new String[] {id+""});
db.close();
}
public Goal readGoalFromDb(int id) { //method to get a goal from the database
SQLiteDatabase db = this.getWritableDatabase();
Cursor cursor = db.query(TABLE_GOALS, new String[] { KEY_ID,
KEY_STROKE, KEY_TIME_HRS, KEY_TIME_MIN, KEY_TIME_SECS, KEY_DISTANCE, KEY_ACHIEVED, KEY_DATE_GOAL }, KEY_ID + "=?",
new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();
Goal goal = new Goal(cursor.getInt(0), cursor.getString(1), cursor.getInt(2),
cursor.getInt(3), cursor.getInt(4),
cursor.getInt(5), Boolean.parseBoolean(cursor.getString(6)), cursor.getString(7));
cursor.close();
db.close();
return goal;
}
makeGoalsFromDB:
public void makeGoalsFromDB() {
//looping through the table, get the goals and add them to the goals list
goalsList = new ArrayList<Goal>();
int goalsNo = db.getGoalsCount();
for (int i = 1; i <= goalsNo; i++) {
goalsList.add(db.readGoalFromDb(i));
}
}
使用(int,String,int,int,int,int,int,int,int,boolean,String)创建目标
这是我的错误日志:
08-24 12:29:37.850: E/AndroidRuntime(7897): FATAL EXCEPTION: main
08-24 12:29:37.850: E/AndroidRuntime(7897): Process: com.lyncht.swimtracker, PID: 7897
08-24 12:29:37.850: E/AndroidRuntime(7897): android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.database.AbstractCursor.checkPosition(AbstractCursor.java:426)
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.database.AbstractWindowedCursor.getInt(AbstractWindowedCursor.java:68)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.lyncht.swimtracker.DatabaseHandler.readGoalFromDb(DatabaseHandler.java:128)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.lyncht.swimtracker.ViewGoals.makeGoalsFromDB(ViewGoals.java:76)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.lyncht.swimtracker.ViewGoals.deleteGoal(ViewGoals.java:68)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.lyncht.swimtracker.ViewGoals.onContextItemSelected(ViewGoals.java:61)
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.app.Activity.onMenuItemSelected(Activity.java:2620)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.android.internal.policy.impl.PhoneWindow$DialogMenuCallback.onMenuItemSelected(PhoneWindow.java:3864)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:741)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:884)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:874)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.android.internal.view.menu.MenuDialogHelper.onClick(MenuDialogHelper.java:167)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:941)
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.widget.AdapterView.performItemClick(AdapterView.java:299)
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.widget.AbsListView.performItemClick(AbsListView.java:1113)
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.widget.AbsListView$PerformClick.run(AbsListView.java:2911)
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.widget.AbsListView$3.run(AbsListView.java:3645)
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.os.Handler.handleCallback(Handler.java:733)
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.os.Handler.dispatchMessage(Handler.java:95)
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.os.Looper.loop(Looper.java:136)
08-24 12:29:37.850: E/AndroidRuntime(7897): at android.app.ActivityThread.main(ActivityThread.java:5001)
08-24 12:29:37.850: E/AndroidRuntime(7897): at java.lang.reflect.Method.invokeNative(Native Method)
08-24 12:29:37.850: E/AndroidRuntime(7897): at java.lang.reflect.Method.invoke(Method.java:515)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
08-24 12:29:37.850: E/AndroidRuntime(7897): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
08-24 12:29:37.850: E/AndroidRuntime(7897): at dalvik.system.NativeStart.main(Native Method)
就像Frank N.Stein已经说过的:你需要使用你想要删除的目标的数据库id。因此,在onContextItemSelected中,编写如下内容:
int idToDelete = listView.getItem(position).getGoalId();
deleteGoal(idToDelete);
在readGoalFromDb(int-id)
Goal goal = null;
if (cursor != null)
if(cursor.moveToFirst()) // IMPORTANT!, check whether the returned cursor is empty
{
goal = new Goal(cursor.getInt(0), cursor.getString(1), cursor.getInt(2),
cursor.getInt(3), cursor.getInt(4),
cursor.getInt(5), Boolean.parseBoolean(cursor.getString(6)), cursor.getString(7));
return goal;
}
else {
//the returned cursor is empty
Log.v("cursorempty","the cursor was returned empty");
return null
}
您检查了null
,但没有检查光标是否有项目。您只是尝试检索导致CursorIndexOutOfBoundsException
的值
如果返回的光标
为空,请采取适当的操作
将您的makeGoalsFromDB()
修改为:
public void makeGoalsFromDB() {
//looping through the table, get the goals and add them to the goals list
goalsList = new ArrayList<Goal>();
int goalsNo = db.getGoalsCount();
for (int i = 1; i <= goalsNo; i++) {
if(null != db.readGoalFromDb(i))
goalsList.add(db.readGoalFromDb(i));
}
}
public void makeGoalsFromDB(){
//在表格中循环,获取目标并将其添加到目标列表中
goalsList=newarraylist();
int goalsNo=db.getGoalsCount();
对于(inti=1;i对于其他有相同问题的人,这里是我最后如何解决的。
在我的数据库处理程序类中,我创建了一个新方法,该方法将遍历goals表中的所有项,如果现在找到了该行(已删除)跳过它并增加一个计数器,如果找到该行,则将目标添加到arraylist。如果一行中空行的计数器达到25,则光标停止搜索,并且我将arraylist中的所有空白项删除
通过添加验证以检查光标是否为空,并跳过项目(如果为空),则会停止尝试到达错误项目时出现光标索引错误或空指针异常。通过在Activity中的deleteGoal中使用idGoal值,意味着它将不引用空行
创建目标arraylist的新方法:(在数据库处理程序类内)
新的目标方法:
public void deleteGoal(int id) {
db.deleteGoalFromDb(id); //deletes the goal from the database
makeGoalsFromDB(); //refreshes the goalsList
}
public void deleteGoal(int position) {
Goal g = goalsList.get(position); //go to goal in goallist
db.deleteGoalFromDb(g.idGoal); //deletes the goal from the database, using its id stored in the object
//Below code will refresh the screen
ListView lview = (ListView) findViewById(R.id.GoalsTable);
populateList();
ListViewAdapter adapter = new ListViewAdapter(this, list);
lview.setAdapter(adapter);
}
数据库处理程序类中的deleteGoalFromDb方法保持不变。Wild guess(因为ut是一个常见错误,所以甚至没有阅读代码):您是否使用ListView项位置作为id来删除行?!我使用的是一个从位置计算的值,该值是项的实际id。您永远不应该依赖项位置相对于表id,因为它们没有任何关系,除非您不将实际id存储在项位置。在这种情况下为什么删除最新的项目效果很好?假设您有55行。您删除了第55行(id=54)。然后插入另一个项目(id=55-惊喜!不再是54!)。重新加载ListView时,此项目编号为54…请立即尝试删除最后一行!我应该在何处返回目标对象?由于它是在if语句中创建的,因此我得到错误“目标无法解析为变量”,在同一位置仍有错误,但现在它是“局部变量目标可能尚未初始化”现在填充goalsList时出现空指针异常,您知道如何解决此问题吗?请检查我的编辑,并在执行时检查日志。现在,当再次加载活动时删除项目时,所有目标都已删除
public ArrayList<Goal> readAllGoals(){
ArrayList<Goal> goalReturnList = new ArrayList<Goal>();
SQLiteDatabase db = this.getWritableDatabase();
String selectQuery = "SELECT * FROM " + TABLE_GOALS; // Query to select all from goals table
Cursor cursor = db.rawQuery(selectQuery, null);
int counter = 0;
int noFalse = 0;
boolean z = true;
while(z) { //the loop will check if there is a record or not and skip past blank records
if(cursor.moveToPosition(counter)&&noFalse<25){ //if it can get to the next position and there has not been 25 missing in a row
noFalse = 0; //Reset the counter for number of missing in a row
Goal goal = new Goal(cursor.getInt(0), cursor.getString(1), cursor.getInt(2),
cursor.getInt(3), cursor.getInt(4),
cursor.getInt(5), Boolean.parseBoolean(cursor.getString(7)), cursor.getString(6)); //Create the goal to add
goalReturnList.add(goal); //Add it to the list
}else if(noFalse>=25){
z = false;
}else{
noFalse++; //Add to the number of false in a row
}
counter++; //Increment the counter
}
cursor.close();
db.close();
for (Goal g: goalReturnList){
if (g.strokeGoal.equals("")) { //strip blank goals
goalReturnList.remove(g);
}
}
return goalReturnList;
}
public boolean onContextItemSelected(MenuItem item) { //what to do when menu item clicked in context menu
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
deleteGoal(info.position);
return true;
}
public void deleteGoal(int position) {
Goal g = goalsList.get(position); //go to goal in goallist
db.deleteGoalFromDb(g.idGoal); //deletes the goal from the database, using its id stored in the object
//Below code will refresh the screen
ListView lview = (ListView) findViewById(R.id.GoalsTable);
populateList();
ListViewAdapter adapter = new ListViewAdapter(this, list);
lview.setAdapter(adapter);
}