java - fatal error - CursorIndexOutOf BoundsException :Index 0 requested ,,大小为 0

标签 java android sqlite android-contentprovider android-adapter

我正在开发记事本应用程序。 NotesDbAdapter 是 ContentProvider。 NoteEdit(编辑笔记)和 NoteList(显示已经从数据库创建的笔记)。当我从 NoteList 到 NoteEdit 类发出 Intent 时,应用程序崩溃并出现此 fatal error 。

我的日志

 04-17 17:49:41.981: E/Trace(26753): error opening trace file: No such file or directory  (2)
 04-17 17:49:45.071: E/AndroidRuntime(26753): FATAL EXCEPTION: main
04-17 17:49:45.071: E/AndroidRuntime(26753): java.lang.RuntimeException: Unable to      start activity ComponentInfo{com.example.note/com.example.note.contentprovider.NoteEdit}:  android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
 04-17 17:49:45.071: E/AndroidRuntime(26753):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074)
 04-17 17:49:45.071: E/AndroidRuntime(26753):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2099)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at android.app.ActivityThread.access$600(ActivityThread.java:138)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1205)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at android.os.Handler.dispatchMessage(Handler.java:99)
 04-17 17:49:45.071: E/AndroidRuntime(26753):   at android.os.Looper.loop(Looper.java:137)
 04-17 17:49:45.071: E/AndroidRuntime(26753):   at android.app.ActivityThread.main(ActivityThread.java:4929)
 04-17 17:49:45.071: E/AndroidRuntime(26753):   at java.lang.reflect.Method.invokeNative(Native Method)
 04-17 17:49:45.071: E/AndroidRuntime(26753):   at java.lang.reflect.Method.invoke(Method.java:511)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at  com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565)
 04-17 17:49:45.071: E/AndroidRuntime(26753):   at dalvik.system.NativeStart.main(Native Method)
 04-17 17:49:45.071: E/AndroidRuntime(26753): Caused by: android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0
04-17 17:49:45.071: E/AndroidRuntime(26753):    at android.database.AbstractCursor.checkPosition(AbstractCursor.java:418)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at android.database.CursorWrapper.getString(CursorWrapper.java:114)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at com.example.note.contentprovider.NoteEdit.populateFields(NoteEdit.java:265)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at com.example.note.contentprovider.NoteEdit.onCreate(NoteEdit.java:71)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at android.app.Activity.performCreate(Activity.java:5254)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1082)
04-17 17:49:45.071: E/AndroidRuntime(26753):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2038)
04-17 17:49:45.071: E/AndroidRuntime(26753):    ... 11 more

NotesDbAdapter.java

public class NotesDbAdapter extends ContentProvider{

private Context mCtx;
     static final String PROVIDER_NAME = "com.example.note.contentprovider.notesdbadapter";
     static final String URL = "content://" + PROVIDER_NAME + "/notes";
     static final Uri CONTENT_URI = Uri.parse(URL);

public static final String KEY_TITLE = "title";
public static final String KEY_DATE = "date";
public static final String KEY_BODY = "body";
public static final String KEY_ROWID = "_id";

public static final int NOTES = 1;
public static final int NOTES_ID = 2;

private static HashMap<String,String> Notes;

static final UriMatcher uriMatcher;
       static{
          uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
          uriMatcher.addURI(PROVIDER_NAME, "notes", NOTES);
          uriMatcher.addURI(PROVIDER_NAME, "notes/#", NOTES_ID);
       }

private static final String TAG = "NotesDbAdapter";
private DatabaseHelper mhelper;
private SQLiteDatabase database;
private static final String DATABASE_NAME = "data";
private static final String DATABASE_TABLE = "notes";
private static final int DATABASE_VERSION = 2;

private static final String DATABASE_CREATE =
    "create table notes (_id integer primary key autoincrement, "
    + "title text not null, body text not null, date text not null);";

private static class DatabaseHelper extends SQLiteOpenHelper {

    DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(DATABASE_CREATE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                + newVersion + ", which will destroy all old data");
        db.execSQL("DROP TABLE IF EXISTS notes");
        onCreate(db);
    }
}

public boolean onCreate() {
            // TODO Auto-generated method stub
            Context context = getContext();
            mhelper = new DatabaseHelper(context);
            // permissions to be writabl
            database =mhelper.getWritableDatabase();
            if(database == null)
                return false;
            else
                return true;   
        }

@Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        // TODO Auto-generated method stub
         SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
         // the TABLE_NAME to query on
         queryBuilder.setTables(DATABASE_TABLE);
          switch (uriMatcher.match(uri)) {
          // maps all database column names
          case NOTES:
              queryBuilder.setProjectionMap(Notes);
             break;
          case NOTES_ID:
              queryBuilder.appendWhere( KEY_ROWID + "=" + uri.getLastPathSegment());
             break;
          default:
             throw new IllegalArgumentException("Unknown URI " + uri);
          }
          Cursor cursor = queryBuilder.query(database, projection, selection,
                  selectionArgs, null, null, sortOrder);

          cursor.setNotificationUri(getContext().getContentResolver(), uri);
          return cursor;
    }

@Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO Auto-generated method stub
        long row = database.insert(DATABASE_TABLE, "", values);
        // If record is added successfully
          if(row > 0) {
             Uri newUri = ContentUris.withAppendedId(CONTENT_URI, row);
             getContext().getContentResolver().notifyChange(newUri, null);
             return newUri;
          }
          throw new SQLException("Fail to add a new record into " + uri);
    }

@Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        // TODO Auto-generated method stub
         int count = 0;
          switch (uriMatcher.match(uri)){
          case NOTES:
             count = database.update(DATABASE_TABLE, values, selection, selectionArgs);
             break;
          case NOTES_ID:
             count = database.update(DATABASE_TABLE, values, KEY_ROWID +
                     " = " + uri.getLastPathSegment() +
                     (!TextUtils.isEmpty(selection) ? " AND (" +
                     selection + ')' : ""), selectionArgs);
             break;
          default:
             throw new IllegalArgumentException("Unsupported URI " + uri );
          }
          getContext().getContentResolver().notifyChange(uri, null);
          return count;
    }

@Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // TODO Auto-generated method stub
        int count = 0;
         switch (uriMatcher.match(uri)){
          case NOTES:
              // delete all the records of the table
              count = database.delete(DATABASE_TABLE, selection, selectionArgs);
              break;
          case NOTES_ID:
              String id = uri.getLastPathSegment(); //gets the id
              count = database.delete( DATABASE_TABLE, KEY_ROWID +  " = " + id +
                    (!TextUtils.isEmpty(selection) ? " AND (" +
                    selection + ')' : ""), selectionArgs);
              break;
          default:
              throw new IllegalArgumentException("Unsupported URI " + uri);
          }
          getContext().getContentResolver().notifyChange(uri, null);
          return count;
    }

@Override
    public String getType(Uri uri) {
        // TODO Auto-generated method stub
        switch (uriMatcher.match(uri)){
          // Get all friend-birthday record
          case NOTES:
             return "vnd.android.cursor.dir/vnd.com.example.note.contentprovider.notesdbadapter/notes";
          // Get a particular friend
          case NOTES_ID:
             return "vnd.android.cursor.item/vnd.com.example.note.contentprovider.notesdbadapter/notes";
          default:
             throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
    }


 public NotesDbAdapter(){

   }

    public NotesDbAdapter(Context ctx) {
     this.mCtx = ctx;

   }

  public NotesDbAdapter open() throws SQLException {
    mhelper = new DatabaseHelper(mCtx);
    database = mhelper.getWritableDatabase();
   return this;
   }

   public void close() {
    mhelper.close();
    }

NoteEdit.java

public class NoteEdit extends Activity{

public static int numTitle = 1; 
public static String curDate = "";
public static String curText = "";  
private EditText mTitleText;
private EditText mBodyText;
private TextView mDateText;
private Long mRowId;
private String mode;
private Cursor note;

private NotesDbAdapter mDbHelper;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

 //   mDbHelper = new NotesDbAdapter(this);
 //   mDbHelper.open();        

    setContentView(R.layout.note_edit);
    setTitle(R.string.app_name);

    mTitleText = (EditText) findViewById(R.id.title);
    mBodyText = (EditText) findViewById(R.id.body);
    mDateText = (TextView) findViewById(R.id.notelist_date);

    long msTime = System.currentTimeMillis();  
    Date curDateTime = new Date(msTime);

    SimpleDateFormat formatter = new SimpleDateFormat("d'/'M'/'y");  
    curDate = formatter.format(curDateTime);        

    mDateText.setText(""+curDate);


    mRowId = (savedInstanceState == null) ? null :
        (Long) savedInstanceState.getSerializable(NotesDbAdapter.KEY_ROWID);
    if (mRowId == null) {
        Bundle extras = getIntent().getExtras();
        mode = extras.getString("mode");
        mRowId = extras != null ? extras.getLong(NotesDbAdapter.KEY_ROWID)
                                : null;
    }

    populateFields();

}

  public static class LineEditText extends EditText{
        // we need this constructor for LayoutInflater
        public LineEditText(Context context, AttributeSet attrs) {
            super(context, attrs);
                mRect = new Rect();
                mPaint = new Paint();
                mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
                mPaint.setColor(Color.BLUE);
        }

        private Rect mRect;
        private Paint mPaint;       

        @Override
        protected void onDraw(Canvas canvas) {

            int height = getHeight();
            int line_height = getLineHeight();

            int count = height / line_height;

            if (getLineCount() > count)
                count = getLineCount();

            Rect r = mRect;
            Paint paint = mPaint;
            int baseline = getLineBounds(0, r);

            for (int i = 0; i < count; i++) {

                canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
                baseline += getLineHeight();

            super.onDraw(canvas);
        }

    }
  }

  @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        saveState();
        outState.putSerializable(NotesDbAdapter.KEY_ROWID, mRowId);
    }

    @Override
    protected void onPause() {
        super.onPause();
        saveState();
    }

    @Override
    protected void onResume() {
        super.onResume();
        populateFields();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.noteedit_menu, menu);

        return true;        
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_delete:
            if(note != null){
                note.close();
                note = null;
            }
            if(mRowId != null){
                //mDbHelper.deleteNote(mRowId);
                Uri uri = Uri.parse(NotesDbAdapter.CONTENT_URI+"/"+mRowId);
                //getContentResolver().delete(uri, null, null);
                mDbHelper.delete(uri,null,null);
            }
            finish();

            return true;
        case R.id.menu_save:
            saveState();


            finish();           
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    private void saveState() {
        String title = mTitleText.getText().toString();
        String body = mBodyText.getText().toString();
        String date = mDateText.getText().toString();

        ContentValues values = new ContentValues();
        values.put(NotesDbAdapter.KEY_TITLE, title);
        values.put(NotesDbAdapter.KEY_BODY, body);
        values.put(NotesDbAdapter.KEY_DATE,date);

        if(mode.trim().equalsIgnoreCase("add")){
        getContentResolver().insert(NotesDbAdapter.CONTENT_URI,values);
            }
              else {
                    Uri uri = Uri.parse(NotesDbAdapter.CONTENT_URI + "/" + mRowId);
                    getContentResolver().update(uri, values, null, null);
                   }    
            }


 private void populateFields() {
        if (mRowId != null) {
            String[] projection = { 
                    NotesDbAdapter.KEY_ROWID,
                    NotesDbAdapter.KEY_TITLE,
                    NotesDbAdapter.KEY_BODY,
                    NotesDbAdapter.KEY_DATE};
                  Uri uri = Uri.parse(NotesDbAdapter.CONTENT_URI + "/" + mRowId);
                  Cursor cursor = getContentResolver().query(uri, projection, null, null,
                    null);
                  if (cursor != null) {
                   cursor.moveToFirst();
                   String title = cursor.getString(cursor.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE));
                   String body = cursor.getString(cursor.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY));
                  String date = cursor.getString(cursor.getColumnIndexOrThrow(NotesDbAdapter.KEY_DATE));
                   mTitleText.setText(title);
                   mBodyText.setText(body);
                   mDateText.setText(date);
                  }
        }
    }

笔记列表.java

     public class NoteList extends ListActivity implements LoaderManager.LoaderCallbacks<Cursor>{

private SimpleCursorAdapter dataAdapter;

private static final int ACTIVITY_CREATE=0;
private static final int ACTIVITY_EDIT=1;

private static final int DELETE_ID = Menu.FIRST;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.notelist);
//  mDbHelper = new NotesDbAdapter(this);
//  mDbHelper.open();
    fillData();             
    registerForContextMenu(getListView());
    Button addnote = (Button)findViewById(R.id.addnotebutton);
    addnote.setOnClickListener(new View.OnClickListener() {     
        @Override
        public void onClick(View v) {
            createNote();
            }
    });
    }


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.notelist_menu, menu);
    return true;        
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
            return super.onOptionsItemSelected(item);
        }


private void createNote() {
    Intent i = new Intent(this, NoteEdit.class);
    Bundle bundle = new Bundle();
     bundle.putString("mode", "add");
     i.putExtras(bundle);
    startActivityForResult(i, ACTIVITY_CREATE);     
}

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);
    Intent i = new Intent(this, NoteEdit.class);
    Bundle bundle = new Bundle();
    bundle.putString("mode", "update");
    bundle.putLong(NotesDbAdapter.KEY_ROWID, id);
    i.putExtras(bundle);
  //  i.putExtra(NotesDbAdapter.KEY_ROWID, id);
    startActivityForResult(i, ACTIVITY_EDIT);
}

private void fillData() {
 // The desired columns to be bound
    String[] columns = new String[] {
      NotesDbAdapter.KEY_TITLE,
      NotesDbAdapter.KEY_DATE
    };

    // the XML defined views which the data will be bound to
    int[] to = new int[] { 
      R.id.text1,
      R.id.date_row
    };

    // create an adapter from the SimpleCursorAdapter
    dataAdapter = new SimpleCursorAdapter(
      this, 
      R.layout.notes_row, 
      null, 
      columns, 
      to,
      0);

    setListAdapter(dataAdapter);
    //Ensures a loader is initialized and active.
    getLoaderManager().initLoader(0, null, this);

}

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    menu.add(0, DELETE_ID, 0, R.string.menu_delete);
}

@Override
public boolean onContextItemSelected(MenuItem item) {
    switch(item.getItemId()) {
        case DELETE_ID:
            AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
           // mDbHelper.deleteNote(info.id);

            Uri uri = Uri.parse(NotesDbAdapter.CONTENT_URI + "/" + info.id);
            getContentResolver().delete(uri, null, null);

            fillData();
            return true;
    }
    return super.onContextItemSelected(item);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    fillData();        
}   


protected void onResume() {
      super.onResume();
      //Starts a new or restarts an existing Loader in this manager
      getLoaderManager().restartLoader(0, null, this);
     }


 // This is called when a new Loader needs to be created.
 @Override
 public Loader<Cursor> onCreateLoader(int id, Bundle args) {
  String[] projection = { 
    NotesDbAdapter.KEY_ROWID,
    NotesDbAdapter.KEY_TITLE, 
    NotesDbAdapter.KEY_BODY, 
    NotesDbAdapter.KEY_DATE};
  CursorLoader cursorLoader = new CursorLoader(this,
    NotesDbAdapter.CONTENT_URI, projection, null, null, null);
  return cursorLoader;
 }

 @Override
 public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
  // Swap the new cursor in.  (The framework will take care of closing the
        // old cursor once we return.)
        dataAdapter.swapCursor(data);
 }

 @Override
 public void onLoaderReset(Loader<Cursor> loader) {
  // This is called when the last Cursor provided to onLoadFinished()
  // above is about to be closed.  We need to make sure we are no
  // longer using it.
  dataAdapter.swapCursor(null);
 }

最佳答案

这部分在这里

if (cursor != null) {
    cursor.moveToFirst();
   String title = cursor.getString(cursor.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE));
   String body = cursor.getString(cursor.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY));
   String date = cursor.getString(cursor.getColumnIndexOrThrow(NotesDbAdapter.KEY_DATE));
   mTitleText.setText(title);
   mBodyText.setText(body);
   mDateText.setText(date);
}

你需要检查游标中是否有任何东西,所以将 cursor.moveToFirst() 移到 if 语句中

关于java - fatal error - CursorIndexOutOf BoundsException :Index 0 requested ,,大小为 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23139616/

相关文章:

java - 当初始化变量链接到另一个变量时?

mysql - Rails 3.2.3 希望在 mysql 生产环境中使用 sqlite3 gem

android - 使用 ORDER BY 时出现数据类型不匹配错误

java - 添加新节点添加 LinkedList 的开头和末尾

java - Eclipse 密码恢复

java - AppEngine Blob 上传速度极慢

android - 无法应用插件 'com.android.internal.application' Android Gradle 插件需要 Java 11 才能运行。您当前使用的是 Java 1.8

android - 在 Bundle 中传递对象 - ClassNotFoundException

java - 在 Java 中修改 XML

android - 查询FTS表MIN