我正在尝试编写一个简单的随机数应用程序。我有随机发生器按钮工作,但后来我改变了一些代码(我认为这与随机化器按钮无关),它开始崩溃,并获得“请求CursorIndexOutOfBoundsException索引0,大小为0”错误。我找不到任何适用于我的代码的修复程序。谁能帮我解决这个问题?
这是我的主要课程按钮:
package com.example.randomgamechooser;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class MainScreen extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
}
public void chooseGame (View view) {
GameList dbUtil = new GameList(this);
dbUtil.open();
String string = dbUtil.getRandomEntry();
//TextView textView = new TextView(this);
TextView textView = (TextView) findViewById(R.id.chosenbox);
textView.setTextSize(40);
textView.setText(string);
//setContentView (textView);
dbUtil.close();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_screen, menu);
return true;
}
//starts the Game Selection activity
public void openGames (View view) {
Intent intent = new Intent(this, GameSelction.class);
startActivity(intent);
}
}
这是GameList类:
package com.example.randomgamechooser;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import java.util.Random;
public class GameList {
private static final String TAG = "GameList";
//database name
private static final String DATABASE_NAME = "game_list";
//database version
private static final int DATABASE_VERSION = 1;
//table name
private static final String DATABASE_TABLE = "game_list";
//table columns
public static final String KEY_NAME = "name";
public static final String KEY_GENRE = "genre";
public static final String KEY_ROWID = "_id";
//database creation sql statement
private static final String CREATE_GAME_TABLE =
"create table " + DATABASE_TABLE + " (" + KEY_ROWID + " integer primary key autoincrement, "
+ KEY_NAME +" text not null, " + KEY_GENRE + " text not null);";
//Context
private final Context mCtx;
private DatabaseHelper mDbHelper;
private static SQLiteDatabase mDb;
//Inner private class. Database Helper class for creating and updating database.
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// onCreate method is called for the 1st time when database doesn't exists.
@Override
public void onCreate(SQLiteDatabase db) {
Log.i(TAG, "Creating DataBase: " + CREATE_GAME_TABLE);
db.execSQL(CREATE_GAME_TABLE);
}
//onUpgrade method is called when database version changes.
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
+ newVersion);
}
}
//Constructor - takes the context to allow the database to be opened/created
//@param ctx the Context within which to work
public GameList(Context ctx) {
this.mCtx = ctx;
}
//This method is used for creating/opening connection
//@return instance of GameList
//@throws SQLException
public GameList open() throws SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}
//This method is used for closing the connection.
public void close() {
mDbHelper.close();
}
//This method is used to create/insert new game.
//@param name
// @param genre
// @return long
public long createGame(String name, String genre) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_NAME, name);
initialValues.put(KEY_GENRE, genre);
return mDb.insert(DATABASE_TABLE, null, initialValues);
}
// This method will delete game.
// @param rowId
// @return boolean
public static boolean deleteGame(long rowId) {
return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}
// This method will return Cursor holding all the games.
// @return Cursor
public Cursor fetchAllGames() {
return mDb.query(DATABASE_TABLE, new String[] {KEY_ROWID, KEY_NAME,
KEY_GENRE}, null, null, null, null, null);
}
// This method will return Cursor holding the specific game.
// @param id
// @return Cursor
// @throws SQLException
public Cursor fetchGame(long id) throws SQLException {
Cursor mCursor =
mDb.query(true, DATABASE_TABLE, new String[] {KEY_ROWID,
KEY_NAME, KEY_GENRE}, KEY_ROWID + "=" + id, null,
null, null, null, null);
if (mCursor != null) {
mCursor.moveToFirst();
}
return mCursor;
}
public int getAllEntries()
{
Cursor cursor = mDb.rawQuery(
"SELECT COUNT(name) FROM game_list", null);
if(cursor.moveToFirst()) {
return cursor.getInt(0);
}
return cursor.getInt(0);
}
public String getRandomEntry()
{
//id = getAllEntries();
Random random = new Random();
int rand = random.nextInt(getAllEntries());
if(rand == 0)
++rand;
Cursor cursor = mDb.rawQuery(
"SELECT name FROM game_list WHERE _id = " + rand, null);
if(cursor.moveToFirst()) {
return cursor.getString(0);
}
return cursor.getString(0);
}
// This method will update game.
// @param id
// @param name
// @param standard
// @return boolean
public boolean updateGame(int id, String name, String standard) {
ContentValues args = new ContentValues();
args.put(KEY_NAME, name);
args.put(KEY_GENRE, standard);
return mDb.update(DATABASE_TABLE, args, KEY_ROWID + "=" + id, null) > 0;
}
}
这是错误日志的原因部分:
08-01 13:03:38.325: E/AndroidRuntime(278): Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
08-01 13:03:38.325: E/AndroidRuntime(278): at android.database.AbstractCursor.checkPosition(AbstractCursor.java:580)
08-01 13:03:38.325: E/AndroidRuntime(278): at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:214)
08-01 13:03:38.325: E/AndroidRuntime(278): at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:41)
08-01 13:03:38.325: E/AndroidRuntime(278): at com.example.randomgamechooser.GameList.getRandomEntry(GameList.java:153)
编辑:这是ListView类:
public class GameSelction extends Activity
{
GameList dbUtil = new GameList(this);
private SimpleCursorAdapter dataAdapter;
//@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_selction);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
getActionBar() .setDisplayHomeAsUpEnabled(true);
}
displayListView();
}
private void displayListView() {
dbUtil.open();
Cursor cursor = dbUtil.fetchAllGames();
// The desired columns to be bound
String[] columns = new String[] {
GameList.KEY_NAME,
GameList.KEY_GENRE,
};
// the XML defined views which the data will be bound to
int[] to = new int[] {
R.id.name,
R.id.genre,
};
// create the adapter using the cursor pointing to the desired data
//as well as the layout information
dataAdapter = new SimpleCursorAdapter(
this, R.layout.game_info,
cursor,
columns,
to,
0);
ListView listView = (ListView) findViewById(R.id.listView1);
// Assign adapter to ListView
listView.setAdapter(dataAdapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> listView, View view,
int position, long rowId) {
// Get the cursor, positioned to the corresponding row in the result set
//Cursor cursor = (Cursor) listView.getItemAtPosition(position);
GameList.deleteGame(rowId);
}
});
}
/**
* Set up the {@link android.app.ActionBar}, if the API is available.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setupActionBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
//opens the AddGame activity
public void openAddgame (View view) {
Intent intent = new Intent(this, AddGame.class);
startActivity(intent);
}
public void buttonBackMain (View view) {
Intent intent = new Intent(this, MainScreen.class);
startActivity(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.game_selction, menu);
return true;
}
}
答案 0 :(得分:1)
问题出在这段代码中:
public String getRandomEntry()
{
//...
Cursor cursor = mDb.rawQuery(
"SELECT name FROM game_list WHERE _id = " + rand, null);
if(cursor.moveToFirst()) {
return cursor.getString(0);
}
return cursor.getString(0);
}
你最后做的是说return cursor.getString(0);
光标是否有结果。所以删除第二个匹配项,它应该可以工作。
修改强> 扫描代码后,似乎唯一使用此方法的地方是填充TextView。在这种情况下,您可以将此作为向您自己或您的用户传达可视错误消息的机会,或者使用您想要的任何其他内容。所以我建议使用某些东西来实现
的效果public String getRandomEntry()
{
//EDIT: This will make your random generator less biased toward 1.
Random random = new Random();
int rand = random.nextInt(getAllEntries()) + 1;
/* Assuming your _id starts at 1 and auto-increments, this will
* start the random digits at 1 and go as high as your highest _id */
Cursor cursor = mDb.rawQuery(
"SELECT name FROM game_list WHERE _id = " + rand, null);
if(cursor.moveToFirst()) {
return cursor.getString(0);
}
return "There were no games in the database to choose from.";
}
修改强>
试试这个。请注意,此代码使用您在其他地方使用的mDb.query()
。我不确定为什么rawQuery()
会拒绝工作,但也许会这样做。
public String getRandomEntry()
{
Random random = new Random();
int rand = random.nextInt(getAllEntries()) + 1;
Cursor cursor = mDb.query(true, DATABASE_TABLE, new String[] {KEY_NAME},
KEY_ROWID + "=" + rand, null, null, null, null, null);
if(cursor.moveToFirst()) {
return cursor.getString(0);
}
return "There were no games in the database to choose from.";
}
答案 1 :(得分:0)
根据初始外观,SQLiteDatabase
代表的mDB
对象似乎是空的,因为这就是抛出错误的内容。
错误的含义是您的代码在索引0处请求项目(基本上是第一项),但索引的大小为0(基本上,索引中没有项目)。
在该行的某处,您的数据库对象要么已清空,要么未填充。要对此进行测试,请运行fetchAllGames
方法并验证索引的内容。
答案 2 :(得分:0)
没有阅读整个代码,但我想问题是,你试图从空数据库中获取第一个元素。 在获取元素之前,只需检查光标的大小是否大于0。
if (cursor.getColumnCount() > 0)
return cursor.getString(0);
else return "no items";