Я получаю android.database.CursorIndexOutOfBoundsException: запрашивается индекс 0 с размером ошибки 0 при попытке перечислить данные из базы данных Sqlite. Из чтения других проблем с той же ошибкой могу сказать, что для первой записи есть нулевое значение. Разрешение, похоже, заключается в том, чтобы закрыть курсор, но я уже делаю это, поэтому это не может быть причиной. Если я неправильно закрываю курсор. Я отправляю сообщение об ошибке, которое я получаю, и код, который, как мне кажется, связан с ошибкой. Любые рекомендации по устранению этой ошибки будут оценены.
Process: ca.rvogl.tpbcui, PID: 30793
android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
at android.database.AbstractCursor.checkPosition(AbstractCursor.java:460)
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
at android.database.AbstractWindowedCursor.getInt(AbstractWindowedCursor.java:68)
at ca.rvogl.tpbcui.Database.DatabaseHelper.getGame(DatabaseHelper.java:445)
at ca.rvogl.tpbcui.Views.GameActivity.createGame(GameActivity.java:113)
at ca.rvogl.tpbcui.Views.GameActivity.access$800(GameActivity.java:30)
at ca.rvogl.tpbcui.Views.GameActivity$7.onClick(GameActivity.java:244)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Код из моего DatabaseHelper
public Game getGame(String leagueId, String bowlerId, String seriesId) {
//Get Readable Database If We Are Not Inserting Anything
SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.query( Game.TABLE_NAME,
new String[]{Game.COLUMN_ID, Game.COLUMN_LEAGUE_ID, Game.COLUMN_BOWLER_ID,
Game.COLUMN_SERIES_ID, Game.COLUMN_SCORE, Game.COLUMN_STRIKES, Game.COLUMN_SPARES,Game.COLUMN_SPLITS, Game.COLUMN_SPLIT_CONVERSIONS, Game.COLUMN_OPEN_FRAMES, Game.COLUMN_TIMESTAMP},
Game.COLUMN_LEAGUE_ID + "=?" + " AND " + Game.COLUMN_BOWLER_ID + "=?" + " AND " + Game.COLUMN_SERIES_ID + "=?",
new String[]{String.valueOf(leagueId), String.valueOf(bowlerId), String.valueOf(seriesId)}, null, null, null, null); if (cursor != null)
cursor.moveToFirst(); //Prepare Game Object
Game game = new Game( cursor.getInt(cursor.getColumnIndex(Game.COLUMN_ID)),
cursor.getString(cursor.getColumnIndex(Game.COLUMN_LEAGUE_ID)),
cursor.getString(cursor.getColumnIndex(Game.COLUMN_BOWLER_ID)),
cursor.getString(cursor.getColumnIndex(Game.COLUMN_SERIES_ID)),
cursor.getString(cursor.getColumnIndex(Game.COLUMN_SCORE)),
cursor.getString(cursor.getColumnIndex(Game.COLUMN_STRIKES)),
cursor.getString(cursor.getColumnIndex(Game.COLUMN_SPARES)),
cursor.getString(cursor.getColumnIndex(Game.COLUMN_SPLITS)),
cursor.getString(cursor.getColumnIndex(Game.COLUMN_SPLIT_CONVERSIONS)),
cursor.getString(cursor.getColumnIndex(Game.COLUMN_OPEN_FRAMES)),
cursor.getString(cursor.getColumnIndex(Game.COLUMN_TIMESTAMP))); //Close Database Connection
cursor.close(); return game;
} public List<Game> getAllGames(String leagueId, String bowlerId, String seriesId) {
List<Game> games = new ArrayList<>(); //Select All Query
String selectQuery = "SELECT * FROM " + Game.TABLE_NAME + " WHERE " + Game.COLUMN_LEAGUE_ID + " = '" + leagueId + "'" + " AND " + Game.COLUMN_BOWLER_ID + " = '" + bowlerId + "'" + " AND " + Game.COLUMN_SERIES_ID + " = '" + seriesId + "'" + " ORDER BY " +
Game.COLUMN_TIMESTAMP + " DESC"; try (SQLiteDatabase db = this.getWritableDatabase()) {
@SuppressLint("Recycle") Cursor cursor = db.rawQuery( selectQuery, null ); //Looping Through All Rows And Adding To The List
if (cursor.moveToFirst()) {
do {
Game game1 = new Game();
game1.setId(cursor.getInt(cursor.getColumnIndex(Game.COLUMN_ID ) ) );
game1.setLeagueId(cursor.getString(cursor.getColumnIndex(Game.COLUMN_LEAGUE_ID)));
game1.setBowlerId(cursor.getString(cursor.getColumnIndex(Game.COLUMN_BOWLER_ID)));
game1.setSeriesId(cursor.getString(cursor.getColumnIndex(Game.COLUMN_SERIES_ID)));
game1.setScore(cursor.getString(cursor.getColumnIndex(Game.COLUMN_SCORE)));
game1.setSpares(cursor.getString(cursor.getColumnIndex(Game.COLUMN_SPARES)));
game1.setSplits(cursor.getString(cursor.getColumnIndex(Game.COLUMN_SPLITS)));
game1.setSplitConversions(cursor.getString(cursor.getColumnIndex(Game.COLUMN_SPLIT_CONVERSIONS)));
game1.setOpenFrames(cursor.getString(cursor.getColumnIndex(Game.COLUMN_OPEN_FRAMES)));
game1.setTimestamp(cursor.getString(cursor.getColumnIndex(Game.COLUMN_TIMESTAMP))); games.add( game1 );
} while (cursor.moveToNext());
} //Close Database Connection
db.close();
} //Return Game List
return games;
}
Код из Games.java
//Inserting New Game In The Database & Refreshing The List
private void createGame(String leagueId, String bowlerId, String seriesId, String score, String spares, String strikes, String splits, String splitConversions, String openFrames) {
//Inserting Game In The Database & Getting Newly Inserted Game Id
long id = db.insertGame(leagueId, bowlerId, seriesId, score, strikes, spares, splits, splitConversions, openFrames); //Getting The Newly Inserted Game From The Database
Game n = db.getGame(leagueId, bowlerId, seriesId); if (n != null) {
//Adding New Game To The Array at Position 0
gameList.add(0, n); //Refreshing The List
mAdapter.notifyDataSetChanged(); toggleEmptyGames();
}
} //Updating Game In The Database & Updating Item In The List By Its Position
private void updateGame(String score, String strikes, String spares, String splits, String splitConversions, String openFrames, int position) {
Game n = gameList.get(position);
//Updating the Game Text
n.setScore(score);
n.setStrikes(strikes);
n.setSpares(spares);
n.setSplits(splits);
n.setSplitConversions(splitConversions);
n.setOpenFrames(openFrames); //Updating Game In The Database
db.updateGame(n); //Refreshing The List
gameList.set(position, n);
mAdapter.notifyItemChanged(position); toggleEmptyGames();
} //Deleting Game From SQWLite & Removing The Item From The List By Its Position
private void deleteGame(int position) {
//Deleting Game From The Database
db.deleteGame(gameList.get(position)); //Removing Game From The List
gameList.remove(position);
mAdapter.notifyItemRemoved(position); toggleEmptyGames();
} //Opens Dialog With Edit - Delete Options
private void showActionsDialog(final int position) {
CharSequence colors[] = new CharSequence[]{"Edit", "Delete"}; AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Choose option");
builder.setItems(colors, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == 0) {
showGameDialog(true, gameList.get(position), position);
} else {
deleteGame(position);
}
}
});
builder.show();
}
Эта ошибка появляется только при попытке добавить еще одну игру в базу данных. Когда я перезапускаю приложение, данные, которые были введены, отображаются в списке, но, тем не менее, неверно, что из некоторых полей отсутствуют значения.
Пересмотренный код
public Game getGame(String leagueId, String bowlerId, String seriesId) {
//Get Readable Database If We Are Not Inserting Anything
SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.query( Game.TABLE_NAME,
new String[]{Game.COLUMN_ID, Game.COLUMN_LEAGUE_ID, Game.COLUMN_BOWLER_ID,
Game.COLUMN_SERIES_ID, Game.COLUMN_SCORE, Game.COLUMN_STRIKES, Game.COLUMN_SPARES, Game.COLUMN_SPLITS, Game.COLUMN_SPLIT_CONVERSIONS, Game.COLUMN_OPEN_FRAMES, Game.COLUMN_TIMESTAMP},
Game.COLUMN_LEAGUE_ID + "=?" + " AND " + Game.COLUMN_BOWLER_ID + "=?" + " AND " + Game.COLUMN_SERIES_ID + "=?",
new String[]{String.valueOf( leagueId ), String.valueOf( bowlerId ), String.valueOf( seriesId )}, null, null, null, null ); // if (cursor.getCount()>0)
// cursor.moveToFirst();
// Log.d("Events",Integer.toString(cursor.getCount()));
if (cursor.moveToFirst()) {
//Prepare Game Object
Game game = new Game( cursor.getInt( cursor.getColumnIndex( Game.COLUMN_ID ) ),
cursor.getString( cursor.getColumnIndex( Game.COLUMN_LEAGUE_ID ) ),
cursor.getString( cursor.getColumnIndex( Game.COLUMN_BOWLER_ID ) ),
cursor.getString( cursor.getColumnIndex( Game.COLUMN_SERIES_ID ) ),
cursor.getString( cursor.getColumnIndex( Game.COLUMN_SCORE ) ),
cursor.getString( cursor.getColumnIndex( Game.COLUMN_STRIKES ) ),
cursor.getString( cursor.getColumnIndex( Game.COLUMN_SPARES ) ),
cursor.getString( cursor.getColumnIndex( Game.COLUMN_SPLITS ) ),
cursor.getString( cursor.getColumnIndex( Game.COLUMN_SPLIT_CONVERSIONS ) ),
cursor.getString( cursor.getColumnIndex( Game.COLUMN_OPEN_FRAMES ) ),
cursor.getString( cursor.getColumnIndex( Game.COLUMN_TIMESTAMP ) ) ); //Close Database Connection
cursor.close(); return game;
} else {
}
}
Причина, по которой вы получаете эту ошибку, в два раза. Сначала нет строк, возвращаемых запросом, который затем неправильно проверяется / обрабатывается, когда вы проверяете нулевой курсор, когда курсор возвращается из метода
query
не будет null. Это может быть пусто (cursor.getCount () вернет 0).Все методы курсора
move????
возвращают true или false в зависимости от того, есть или нет перемещение может быть выполнено.Таким образом, чтобы правильно обрабатывать чтение курсора, вы должны никогда использовать (это бесполезно и, как в вашем случае, разрушительно) :
вместо этого вы должны использовать: -
Для циклического перемещения курсора вы можете использовать: -
Если вам нужно прокрутить курсор и не обрабатывать строки в курсоре, вы можете использовать: -
Отмечая, что в каждой ситуации вы должен закрыть курсор, когда закончите с ним.
return game
после предложения if, например.if { ....... return game; } return game;
Отмечая, что игра будет null, когда нет строк.