gpt4 book ai didi

android - 在 Android 中 moveToNext() 失败之前对 getType() 和 getColumnNames() 的 SQL 调用?

转载 作者:行者123 更新时间:2023-11-29 23:16:18 25 4
gpt4 key购买 nike

我想知道是否可以在 moveToNext() 之前调用 getType() 和 getColumnNames()。

基本上,我正在尝试编写以下辅助函数:

 public static int getColumnIndex(Cursor c, String columnName) {
for (int i = 0; i < c.getColumnNames().length; i++) {
String realName = c.getColumnName(i);
if (realName.substring(realName.indexOf(".") + 1).equals(columnName)) {
return i;
}
}
return -1;
}

public static Object getSQLValue(Cursor c, String columnName) {
int index = getColumnIndex(c, columnName);
if (index > -1) {
switch (c.getType(index)) {
case Cursor.FIELD_TYPE_BLOB:
return c.getBlob(index);
case Cursor.FIELD_TYPE_FLOAT:
return c.getFloat(index);
case Cursor.FIELD_TYPE_STRING:
return c.getString(index);
case Cursor.FIELD_TYPE_INTEGER:
return c.getInt(index);
case Cursor.FIELD_TYPE_NULL:
return null;
}
}

return null;
}

但有时我在 c.getType(index) 处遇到错误(来自未与我共享数据库的 beta 测试人员...),其中索引为 0,c 的大小为 0:

 Caused by android.database.CursorIndexOutOfBoundsException
Index 0 requested, with a size of 0

既然 getColumnIndex 应该在出现问题时返回 -1,那么 getColumnIndex 如何返回 0 并且同时 c 在索引 0 处没有列?难道是因为在此之前没有调用“moveToNext()”吗?

谢谢。

最佳答案

简而言之,除非您移动到有效行并且另外要求游标本身具有行,否则您无法获取列类型。

因此你需要

  1. 检查 Cursor 实际上有 1 行或多行(即它不为空)。返回 int 的 Cursor getCount() 方法可用于此目的。

  2. 移动到一个有效的行并为正确移动回到光标之前定位到的行。

因此,我相信以下将是您想要的:-

public static Object getSQLValue(Cursor c, String columnName) {
Log.d("CURSORCOUNT","Cursor has a size of " + String.valueOf(c.getCount())); //<<<<<<<<<< for demo //TODO remove me
Object rv = null;
int rowcount = c.getCount();
if (rowcount < 1) {
return rv;
}
int index = getColumnIndex(c, columnName);
int pos = c.getPosition();
boolean moveback = false;
if (pos < 0 || pos >= rowcount) {
c.moveToFirst();
moveback = true;
}
if (index > -1) {
switch (c.getType(index)) {
case Cursor.FIELD_TYPE_BLOB:
rv = c.getBlob(index);
break;
case Cursor.FIELD_TYPE_FLOAT:
rv = c.getFloat(index);
break;
case Cursor.FIELD_TYPE_STRING:
rv = c.getString(index);
break;
case Cursor.FIELD_TYPE_INTEGER:
rv = c.getInt(index);
break;
}
}
if(moveback) c.moveToPosition(pos);
return rv;
}
  • 请注意,以上内容已经过修改以适应职位的保留。如果 Cursor 已移动到一行(请参阅测试中的 Cursor c3),则该行位置将用于提取数据/类型。但是,如果 Cursor 在第一行之前或之后,则移动到第一行并在返回之前恢复该位置。

测试

假设数据库有一个表和一个具有 bool 参数的 getRows 方法 - 如果为 false,则通过游标检索表中的所有行 - 如果为真,则返回一个空的 Cursor

使用以下测试:-

public class MainActivity extends AppCompatActivity {

DBHelper mDBHlpr;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mDBHlpr = new DBHelper(this); //<<<<<<<<<< The Database Helper
mDBHlpr.getWritableDatabase().delete(DBHelper.TBL_MYTABLE,null,null); //<<<<<<<<<< empty table
// Add some testing data
mDBHlpr.insert("2019-03-25T19:19:39.664Z");
mDBHlpr.insert("\"2019-03-25T19:19:39.664Z\"");

// Get a populated cursor (c1) and and empty cursor (c2)
Cursor c1 = mDBHlpr.getRows(false); //<<<<<<<<<< populated
Cursor c2 = mDBHlpr.getRows(true); //<<<<<<<<< empty
Cursor c3 = mDBHlpr.getRows(false); //<<<<<<<<<< populated for position preservation example
c3.moveToPosition(1); //<<<<<<<<<< moved to 2nd row

// Try with a non-existant column for the populated cursor
logit(DBHelper.getSQLValue(c1,"NOTACOLUMN"),"TEST1 - NOT A COLUMN");
// Try with a valid column for the populated cursor
logit(DBHelper.getSQLValue(c1,DBHelper.COL_MYTABLE_MYSTRING),"TEST2 - VALID COLUMN");
// Try with a non-existant column for the empty cursor
logit(DBHelper.getSQLValue(c2,"NOTACOLUMN"),"TEST3 - NOT A COLUMN - EMPTY CURSOR");
// Try with a valid column for the empty cursor
logit(DBHelper.getSQLValue(c2,DBHelper.COL_MYTABLE_MYSTRING),"TEST4 - VALID COLUMN - EMPTY CURSOR");


//PRESERVATION OF POSITION EXAMPLE
// Try with a valid column for the populated cursor
logit(DBHelper.getSQLValue(c3,DBHelper.COL_MYTABLE_MYSTRING),"TEST2 - VALID COLUMN");
Log.d("PRESERVED_POS", "Position is " + String.valueOf(c3.getPosition()));
}

private void logit(Object o,String tag) {
String msg = "OBJECT IS NULL!!!!";
if (o != null) {
msg = "OBJECT IS " + o.toString();
}
Log.d(tag,msg);
}
}

结果

03-23 13:19:36.175 20570-20570/? D/CURSORCOUNT: Cursor has a size of 2
03-23 13:19:36.176 20570-20570/? D/TEST1 - NOT A COLUMN: OBJECT IS NULL!!!!
03-23 13:19:36.176 20570-20570/? D/CURSORCOUNT: Cursor has a size of 2
03-23 13:19:36.176 20570-20570/? D/TEST2 - VALID COLUMN: OBJECT IS 2019-03-25T19:19:39.664Z
03-23 13:19:36.176 20570-20570/? D/CURSORCOUNT: Cursor has a size of 0
03-23 13:19:36.176 20570-20570/? D/TEST3 - NOT A COLUMN - EMPTY CURSOR: OBJECT IS NULL!!!!
03-23 13:19:36.176 20570-20570/? D/CURSORCOUNT: Cursor has a size of 0
03-23 13:19:36.176 20570-20570/? D/TEST4 - VALID COLUMN - EMPTY CURSOR: OBJECT IS NULL!!!!



03-23 13:19:36.176 20570-20570/? D/CURSORCOUNT: Cursor has a size of 2
03-23 13:19:36.176 20570-20570/? D/TEST2 - VALID COLUMN: OBJECT IS "2019-03-25T19:19:39.664Z"
03-23 13:19:36.176 20570-20570/? D/PRESERVED_POS: Position is 1

重要的是,没有异常,本来应该有异常的地方,按照最后两行,光标位置被保留。

  • 注意,每个不同的行/列组合都可以有自己的类型,除了 rowid 列或其别名(值只能是一个此类列的整数),任何类型的值都可以存储在任何类型的列中。

  • 注意 getInt 可能无法正确检索所有值,因为 INTEGER 的列类型可以存储 64 位有符号值,因此在某些实例可能需要 getLong 才能获取有效值。同样,可能需要 getDouble 而不是 getFloat 来防止精度损失。

关于android - 在 Android 中 moveToNext() 失败之前对 getType() 和 getColumnNames() 的 SQL 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55307158/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com