2013-08-01 2 views
0

간단한 임의 화 프로그램을 코딩하려고합니다. randomizer 버튼이 작동했지만 임의 코드 (무작위 화 단추와 관련이 없다고 생각하는)를 변경하고 충돌하고 "CursorIndexOutOfBoundsException 인덱스 0이 0 크기로 요청 됨"오류가 발생하기 시작했습니다. 내 코드에 적용되는 수정 사항을 찾을 수 없습니다. 아무도 내가이 문제를 해결하도록 도울 수 있습니까? 오류 로그의 원인의 일부가 여기인덱스 0이 필요하며 크기는 0입니다.

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) 
다음
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 클래스입니다 : 여기

버튼 내 주요 클래스

편집 : 다음은 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

mDB으로 표시된 SQLiteDatabase 개체는 처음 모양을 기반으로하므로 오류를 던지고있는 것으로 보입니다.

코드에서 색인 0 (기본적으로 첫 번째 항목)에서 항목을 요청했지만 색인의 크기가 0 (기본적으로 색인에 항목이 없음)이라는 오류가 표시됩니다.

줄을 따라 데이터베이스 객체가 비어 있거나 채워지지 않습니다. 이를 테스트하려면 fetchAllGames 메소드를 실행하고 인덱스의 내용을 확인하십시오.

+0

사실 나는 다른 액티비티/클래스에서 데이터베이스를 ListView로 가져 오는 fetchAllGames 메서드를 실행하면 정상적으로 작동합니다. 모든 것이 나타나듯이. – Matt

+0

죄송합니다. 모든 것이 비어있는 데이터베이스를 가리키고 있습니다. 또는 어쩌면 쿼리가 어딘지 잘못되었을 수 있습니까? 아마도 랜드가 어떻게 든 벗어나고 기본적으로 빈 응답을 얻고 있습니까?_id 값을 하드 코딩하여 테스트 할 수 있습니까? – Deactivator2

1

문제는이 코드 섹션에 : 커서의 결과가 있었다 여부를 return cursor.getString(0); 말을 한 일을 결국 무엇

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); 
    } 

. 따라서 두 번째 발생을 제거하면 제대로 작동합니다.

편집 : 코드를 스캔 한 후에는이 방법을 사용하는 유일한 곳이 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."; 
    } 
+0

불행히도 그것은 작동하지 않았다. 그것은 getRandomEntry가 return 문을 필요로한다고 말합니다. – Matt

+0

아, 맞습니다. 음,'return cursor.getString (0)'을 사용할 수 없습니다. 나는 대체 제안을 편집했다. – Stspurg

+0

어디에 넣어야합니까? – Matt

0

전체 코드를 읽지는 않았지만 문제는 빈 데이터베이스에서 첫 번째 요소를 가져 오는 것입니다. 요소를 가져 오기 전에 커서의 크기가 0보다 큰지 확인하십시오.

if (cursor.getColumnCount() > 0) 
return cursor.getString(0); 
else return "no items"; 
+0

좋아요, 그래서 내가 코멘트에 코드를 형식화하는 방법을 알아낼 수 없지만, 나는 당신이 무엇을 가지고 두 번째 return 문에 "if (cursor.moveToFirst()"에서 코드를 대체했다. 그게 니가 의미하는거야? – Matt

관련 문제