Java 已请求索引0,大小为0
我正在尝试编写一个简单的随机化应用程序。我让randomizer按钮工作,但后来我更改了一些代码(我认为与randomizer按钮无关),它开始崩溃,并得到“CursorIndexOutOfBoundsException索引0请求,大小为0”的错误。我找不到任何适用于我的代码的修复程序。有人能帮我修一下吗 这是我的主要课程,按钮如下:Java 已请求索引0,大小为0,java,android,indexing,cursor,indexoutofboundsexception,Java,Android,Indexing,Cursor,Indexoutofboundsexception,我正在尝试编写一个简单的随机化应用程序。我让randomizer按钮工作,但后来我更改了一些代码(我认为与randomizer按钮无关),它开始崩溃,并得到“CursorIndexOutOfBoundsException索引0请求,大小为0”的错误。我找不到任何适用于我的代码的修复程序。有人能帮我修一下吗 这是我的主要课程,按钮如下: package com.example.randomgamechooser; import android.app.Activity; import andro
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;
}
}
公共类游戏选择扩展活动
{
GameList dbUtil=新游戏列表(此);
私有SimpleCursorAdapter数据适配器;
//@抑制警告(“弃用”)
@SuppressLint(“新API”)
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u game\u Selection);
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.HONEYCOMB){
getActionBar().setDisplayHomeAsUpEnabled(true);
}
displayListView();
}
私有void displayListView(){
dbUtil.open();
Cursor Cursor=dbUtil.fetchAllGames();
//要绑定的所需列
字符串[]列=新字符串[]{
GameList.KEY\u名称,
GameList.KEY_流派,
};
//数据将绑定到的XML定义的视图
int[]到=新的int[]{
R.id.name,
R.id,
};
//使用指向所需数据的光标创建适配器
//以及布局信息
dataAdapter=新的SimpleCorsorAdapter(
这是R.layout.game_信息,
光标,
柱,
到
0);
ListView ListView=(ListView)findViewById(R.id.listView1);
//将适配器分配给ListView
setAdapter(dataAdapter);
setOnItemClickListener(新的OnItemClickListener(){
@凌驾
public void onItemClick(AdapterView列表视图、视图、,
int位置,长rowId){
//获取光标,定位到结果集中的对应行
//游标游标=(游标)listView.getItemAtPosition(位置);
游戏列表。删除游戏(rowId);
}
});
}
/**
*如果API可用,请设置{@link android.app.ActionBar}。
*/
@TargetApi(构建版本代码蜂窝)
私有void setupActionBar(){
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.HONEYCOMB){
getActionBar().setDisplayHomeAsUpEnabled(true);
}
}
//打开AddGame活动
公共void openAddgame(视图){
Intent Intent=新Intent(这个,AddGame.class);
星触觉(意向);
}
公共作废按钮BackMain(视图){
意向意向=新意向(此,MainScreen.class);
星触觉(意向);
}
@凌驾
公共布尔onCreateOptions菜单(菜单){
//为菜单充气;这会将项目添加到操作栏(如果存在)。
getMenuInflater().充气(右菜单。游戏选择,菜单);
返回true;
}
}
根据初始外观,由mDB
表示的SQLiteDatabase
对象似乎是空的,因为这就是引发错误的原因
错误的意思是,代码请求索引0处的项(基本上是第一项),但索引的大小是0(基本上,索引中没有项)
在这个过程中的某个地方,您的数据库对象要么是空的,要么是未填充的。要测试这一点,请运行
fetchAllGames
方法并验证索引的内容。问题出在代码的这一部分:
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);
}
最后你说的是returncursor.getString(0)代码>光标中是否有结果。因此,删除第二个引用,它应该会起作用
编辑:
扫描代码后,似乎您使用此方法的唯一地方是填充文本视图。在这种情况下,您可以利用此机会向您自己或您的用户传达可视错误消息,或者使用它执行任何其他您想要的操作。因此,我建议使用一些类似于
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.";
}
我没有读完整的代码,但我想问题是,您试图从空数据库中获取第一个元素。
在获取元素之前,只需检查光标的大小是否大于0
if (cursor.getColumnCount() > 0)
return cursor.getString(0);
else return "no items";
不幸的是,这不起作用。上面说getRandomEntry需要一个返回语句哦,对了。嗯,您不能使用返回cursor.getString(0)
。我编辑了一个替换建议。代替您的第二个返回声明。我将编辑答案以向您展示。好消息:它已编译。坏消息:“数据库中没有游戏可供选择。”显示是的,我意识到在看到你的其他评论后,ListView显示了一个游戏列表。尝试使用返回整数.toString(getAllEntries())代码>。这将打印出总共有多少个游戏…但没有…random。如果有0个游戏,nextInt()
将抛出异常。这意味着getAllEntries()
知道至少有一个游戏,但您的查询找不到该游戏。我承认,我现在被困在这里了。我会继续查找,但我只确定查询中出现了问题。我确实在另一个活动/类中运行了fetchAllGames方法,该活动/类将数据库作为ListView显示,它工作正常。就像所有的东西都显示出来一样。对不起,所有的东西都指向一个空数据库,或者可能查询不正确?也许兰德是