Android: 确保 Cursor 在访问数据之前正确初始化

Android: Make sure the Cursor is initialized correctly before accessing data from it

我正在尝试构建一个 Android 待办事项列表应用程序,它使用 SQL 数据库来保存用户输入(标题、任务、日期、时间)。在我使用 2 个活动(MainActivity、Dialog)的项目中,我使用的代码使用 onClick(Add_task) 成功保存了用户输入,但是当我使用多个 Cursor 更新列表视图时 UI 它给出了以下错误。

Logcat

08-08 13:42:15.540 6051-6051/com.naive.LISTY E/AndroidRuntime: FATAL EXCEPTION: main
                                                           Process: com.naive.LISTY, PID: 6051
                                                           java.lang.IllegalStateException: Could not execute method for android:onClick
                                                               at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:289)
                                                               at android.view.View.performClick(View.java:5198)
                                                               at android.view.View$PerformClick.run(View.java:21147)
                                                               at android.os.Handler.handleCallback(Handler.java:739)
                                                               at android.os.Handler.dispatchMessage(Handler.java:95)
                                                               at android.os.Looper.loop(Looper.java:148)
                                                               at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                                            Caused by: java.lang.reflect.InvocationTargetException
                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                               at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:284)
                                                               at android.view.View.performClick(View.java:5198) 
                                                               at android.view.View$PerformClick.run(View.java:21147) 
                                                               at android.os.Handler.handleCallback(Handler.java:739) 
                                                               at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                               at android.os.Looper.loop(Looper.java:148) 
                                                               at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                               at java.lang.reflect.Method.invoke(Native Method) 
                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
                                                            Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
                                                               at android.database.CursorWindow.nativeGetString(Native Method)
                                                               at android.database.CursorWindow.getString(CursorWindow.java:438)
                                                               at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
                                                               at listy.naive.com.listy.MainActivity.updateUI(MainActivity.java:102)
                                                               at listy.naive.com.listy.Dialog.Add_task(Dialog.java:58)
                                                               at java.lang.reflect.Method.invoke(Native Method) 
                                                               at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:284) 
                                                               at android.view.View.performClick(View.java:5198) 
                                                               at android.view.View$PerformClick.run(View.java:21147) 
                                                               at android.os.Handler.handleCallback(Handler.java:739) 
                                                               at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                               at android.os.Looper.loop(Looper.java:148) 
                                                               at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                               at java.lang.reflect.Method.invoke(Native Method) 
                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

更新UI

更新UI

public void updateUI() {
    ArrayList<String> taskList = new ArrayList<>();
    SQLiteDatabase db = mHelper.getReadableDatabase();

    Cursor title_cursor = db.query(TaskContract.TaskEntry.TABLE,                                // Cursor Title
            new String[]{TaskContract.TaskEntry._ID, TaskContract.TaskEntry.COL_TASK_TITLE},
            null, null, null, null, null);

    Cursor time_cursor = db.query(TaskContract.TaskEntry.TABLE,                                // Cursor Title
            new String[]{TaskContract.TaskEntry._ID, TaskContract.TaskEntry.COL_TASK_TIME},
            null, null, null, null, null);

    while (title_cursor.moveToNext()) {
        int idx = title_cursor.getColumnIndex(TaskContract.TaskEntry.COL_TASK_TITLE);
        taskList.add(title_cursor.getString(idx));
    }

    if (mAdapter == null) {
        mAdapter = new ArrayAdapter<>(this,
                R.layout.item_todo,
                R.id.task_title,
                taskList);
        mTaskListView.setAdapter(mAdapter);
    } else {
        mAdapter.clear();
        mAdapter.addAll(taskList);
        mAdapter.notifyDataSetChanged();
    }


    while (time_cursor.moveToNext()) {
        int idx = time_cursor.getColumnIndex(TaskContract.TaskEntry.COL_TASK_TITLE);
        taskList.add(time_cursor.getString(idx));
    }

    if (mAdapter == null) {
        mAdapter = new ArrayAdapter<>(this,
                R.layout.item_todo,
                R.id.task_time,
                taskList);
        mTaskListView.setAdapter(mAdapter);
    } else {
        mAdapter.clear();
        mAdapter.addAll(taskList);
        mAdapter.notifyDataSetChanged();
    }

    time_cursor.close();
    title_cursor.close();
    db.close();
}

尝试在访问前将光标移动到第一行:

Cursor time_cursor = db.query(TaskContract.TaskEntry.TABLE,                                // Cursor Title
        new String[]{TaskContract.TaskEntry._ID, TaskContract.TaskEntry.COL_TASK_TIME},
        null, null, null, null, null);
  if(time_cursor != null){
      time_cursor.moveToFirst(); // this is part of cursor initialization

      while (title_cursor.moveToNext()) {
         int idx = title_cursor.getColumnIndex(TaskContract.TaskEntry.COL_TASK_TITLE);
         taskList.add(title_cursor.getString(idx));
      }
  }