【问题标题】:Android: how do I fix timestamp addition to my SQLite database? [duplicate]Android:如何修复我的 SQLite 数据库的时间戳添加? [复制]
【发布时间】:2016-04-28 03:45:05
【问题描述】:

我正在尝试向我的 SQLite 数据库添加一个 TIMESTAMP 列。该列将用于使用“System.currentTimeMillis();”捕获时间戳数据。应用程序正在崩溃,错误来自下面带有 ** ** 的行中的光标代码。错误显示“无法启动活动 ComponentInfo{...ListActivity}:java.lang.IllegalStateException:无法从 CursorWindow 读取第 0 行,第 6 列。请确保在从中访问数据之前正确初始化游标。”

最初我将变量设置为模型文件中的字符串。然后我尝试了很长时间,但都没有奏效。我在这里错过了什么?

用户数据文件:

...
public long getTimestamp() {
    return timestamp;
}

public void setTimestamp(long timestamp) {
    this.timestamp = timestamp;

DatabaseHelper.java 文件:

...
private static final String SQL_CREATE_ENTRIES =
        "CREATE TABLE IF NOT EXISTS " + DBContract.DBEntry.TABLE_NAME +
            "(" + DBContract.DBEntry.COLUMN_NAME_ID +
                  " INTEGER PRIMARY KEY AUTOINCREMENT,"
                + DBContract.DBEntry.COLUMN_NAME_TODO +
                  " TEXT,"
                + DBContract.DBEntry.COLUMN_NAME_NOTE1 +
                  " TEXT,"
                + DBContract.DBEntry.COLUMN_NAME_NOTE2 +
                  " TEXT,"
                + DBContract.DBEntry.COLUMN_NAME_DUEDATE +
                  " TEXT,"
                + DBContract.DBEntry.COLUMN_NAME_DUETIME +
                " TEXT,"
                + DBContract.DBEntry.COLUMN_NAME_TIMESTAMP +
                  " TEXT" + ")";
...

public void insertIntoDB(String todo, String note1, String note2, String duedate, String duetime, long timestamp) {

    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values = new ContentValues();
    values.put(DBContract.DBEntry.COLUMN_NAME_TODO, todo);
    values.put(DBContract.DBEntry.COLUMN_NAME_NOTE1, note1);
    values.put(DBContract.DBEntry.COLUMN_NAME_NOTE2, note2);
    values.put(DBContract.DBEntry.COLUMN_NAME_DUEDATE, duedate);
    values.put(DBContract.DBEntry.COLUMN_NAME_DUETIME, duetime);        
    values.put(DBContract.DBEntry.COLUMN_NAME_TIMESTAMP, timestamp);

    db.insert(DBContract.DBEntry.TABLE_NAME, null, values);
    db.close();
}
...

Cursor cursor = db.rawQuery(query,null);

        try {
            if (cursor.moveToFirst()) {
                do {
                    UserData userData = new UserData();
                    userData.setTodo(cursor.getString(1));
                    userData.setNote1(cursor.getString(2));
                    userData.setNote2(cursor.getString(3));
                    userData.setDuedate(cursor.getString(4));
                    userData.setDuetime(cursor.getString(5));
                    **userData.setTimestamp(cursor.getLong(6));**

                    modelList.add(0, userData);
                    } while (cursor.moveToNext());
...

ListAdapter.java 文件:

...
public void onBindViewHolder(final ListViewHolder holder, final int position) {
    ...
    holder.cardBlankText5.setText((int) dbList.get(position).getTimestamp());

Activity.java 文件:

...
public void onClickSave(View v) {
    ...
    long timestamp=System.currentTimeMillis();
    helper = new DatabaseHelper(Activity.this);
    helper.insertIntoDB(todo,note1,note2,duedate,duetime,timestamp);
    startActivity(new Intent(Activity.this,ListActivity.class));
}

【问题讨论】:

  • rawQuery 调用DatabaseUtils#dumpCursor 之后,你看到了什么?
  • @CL 你的意思是调用 dumpCursor 并显示 Logcat 结果吗?
  • @pskink 在运行 dumpCursor 后显示如下:“E/CursorWindow: 无法从具有 33 行 6 列的 CursorWindow 读取第 0 行第 6 列。”
  • 我想知道我是否应该删除现有数据库,因为它以前只有 5 个数据列(加上 _ID)列)并且已经有数据并从没有数据的新数据库开始,请告知.
  • 什么是传递给 rawQuery 方法的查询?

标签: android sqlite android-recyclerview


【解决方案1】:

DBContract.DBEntry.COLUMN_NAME_TIMESTAMP 作为DATETIME 类型应该可以工作。我通常有一个实用方法,它接受光标和列名并返回一个 Date 对象:

public static Date getDateColumn(Cursor c, String column) {
    Date d = null;
    Long time = c.getLong(c.getColumnIndexOrThrow(column));
    if (time != null && time != 0) {
         d = new Date();
         d.setTime(time);
    }
    return d;
}

要检查的第二件事是您的查询中是否要求该字段。共享 query 的值可能会有所帮助,但通常当您要求的列不在投影中时,您会得到类似的结果。

例如从 mytable 中选择 columnA、columnB;然后你尝试从 columnC 中获取结果中没有的东西。

【讨论】:

  • 对,所以我正在尝试对数据库进行查询并在光标中设置时间戳数据,以便我可以在 RecyclerView 列表中使用光标。不知道如何将您的实用程序方法与我的 userData 对象一起用于光标,如上所示。
  • 只有第 3 行与您相关,因为您希望将其作为 long 存储在 POJO 中,如果要将其存储为 Date 对象,则该方法很有用。无论如何,在表中存储为DATETIME 应该可以解决您的问题。确保在更改表定义后删除您的应用并重新安装它。
  • 所以您建议将 TIMESTAMP 的“TEXT”替换为“DATETIME”?
  • 是的,然后像@Sergey Chechenev 提到的那样卸载应用程序。按住应用程序图标并向上拖动到顶部并转储到卸载中。然后从 Android Studio 再次运行该应用。
  • 好的,用设备(电话)做到了。应用仍然崩溃。
【解决方案2】:

不要尝试从声明为 TEXT 的列中获取 Long。将其声明为 INTEGER。 或者使用 getString() 并将值转换为 Long。

【讨论】:

  • 啊,是的。我会尝试用 INT 替换。
  • 不走运,同样的错误被抛出。
  • 您确定在设备/模拟器上重新创建了数据库吗?或者您使用带有旧值的 db?
  • 首先我清理并重建了项目,然后运行了应用程序。我什至无法进入作为 RecyclerView 列表的活动来输入任何新值。尝试创建列表时应用程序崩溃。
  • 从设备中删除应用并再次运行。清理项目不会从设备中删除应用程序。
猜你喜欢
  • 2015-12-03
  • 1970-01-01
  • 2010-10-21
  • 1970-01-01
  • 2022-07-24
  • 2019-02-11
  • 2020-06-03
  • 1970-01-01
  • 2015-04-23
相关资源
最近更新 更多