Java 已请求索引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

我正在尝试编写一个简单的随机化应用程序。我让randomizer按钮工作,但后来我更改了一些代码(我认为与randomizer按钮无关),它开始崩溃,并得到“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;
    }

}
公共类游戏选择扩展活动
{
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显示,它工作正常。就像所有的东西都显示出来一样。对不起,所有的东西都指向一个空数据库,或者可能查询不正确?也许兰德是