Android 将sqlite查询作为游标或对象/列表返回
几年前,当我启动应用程序时,我做了一些教程,并且总是对返回光标的数据库进行查询(不关闭光标): 现在我正在将代码重构为MVVM并添加模型,因此我将代码更改为:Android 将sqlite查询作为游标或对象/列表返回,android,sqlite,Android,Sqlite,几年前,当我启动应用程序时,我做了一些教程,并且总是对返回光标的数据库进行查询(不关闭光标): 现在我正在将代码重构为MVVM并添加模型,因此我将代码更改为: public Card querySingleId(String szId) { SQLiteDatabase db = getWritableDatabase(); Cursor c1 = db.query(TABLE_ADR, szGetTableEntries, _ID + " = ?", new String[]{
public Card querySingleId(String szId) {
SQLiteDatabase db = getWritableDatabase();
Cursor c1 = db.query(TABLE_ADR, szGetTableEntries, _ID + " = ?", new String[]{szId}, null, null, null);
c1.moveToFirst();
return new Card(c1.getString(c1.getColumnIndex(DbHandler.NAME)),
c1.getString(c1.getColumnIndex(DbHandler.STREET)),
c1.getString(c1.getColumnIndex(DbHandler.CITY)));
}
我读到游标应该总是关闭的(内存泄漏)。从数据库返回数据的最佳/最符合的方法是什么?我也不确定是否有多个结果,我应该使用光标还是更改为列表
public List<Card> queryAll() {
SQLiteDatabase db = getWritableDatabase();
Cursor c1 = db.query(TABLE_ADR, szGetTableEntries, null, null, null, null, null);
List<Card> list = new ArrayList<>();
if(c1.moveToFirst()){
do{
list.add(new Card(c1.getString(c1.getColumnIndex(DbHandler.NAME)),
c1.getString(c1.getColumnIndex(DbHandler.STREET)),
c1.getString(c1.getColumnIndex(DbHandler.CITY))));
} while(c1.moveToNext());
}
c1.close();
return list;
}
public List queryAll(){
SQLiteDatabase db=getWritableDatabase();
游标c1=db.query(表_ADR,szGetTableEntries,null,null,null,null);
列表=新的ArrayList();
if(c1.moveToFirst()){
做{
添加(新卡(c1.getString(c1.getColumnIndex(DbHandler.NAME)),
c1.getString(c1.getColumnIndex(DbHandler.STREET)),
c1.getString(c1.getColumnIndex(DbHandler.CITY));
}而(c1.moveToNext());
}
c1.关闭();
退货清单;
}
这仅仅是一个品味问题,还是有理由返回游标或列表/对象?根据代码中需要数据的位置,列表或光标更方便。
我只是不确定在sqlite查询中什么是正确的方法。代码示例太多了,但似乎大多数都是复制/粘贴,没有真正深入主题。如果查询可以返回多行,那么您应该返回一个列表 如果您确定查询将只返回一张卡,那么返回这张卡就可以了(可能更可取)但是您应该关闭光标
- 但是,没有实际的要求/需要这样做(例如,如果您的初始活动将光标用于ListView/Spinner,则您可能不想关闭光标,而是重新使用光标,并在活动恢复时使用适配器的swapCursor)。光标将被有效地关闭,当应用程序完成时,数据库也将被关闭
- 由于您使用了列_ID,该列通常用于作为rowid列别名的列,该列通常由SQLite生成,因此,如果使用/定义为该列(列已显式或隐式定义为整数主键,带或不带AUTOINCREMENT)然后它将是一个唯一的值,并且只返回一行,因为您有_ID=?。因此,很可能只返回一行或不返回任何行,并且不太可能返回多行
public Card querySingleId(String szId) {
SQLiteDatabase db = getWritableDatabase();
Card rv = null;
Cursor c1 = db.query(TABLE_ADR, szGetTableEntries, _ID + " = ?", new String[]{szId}, null, null, null);
if (c1.moveToFirst()) { //<<<<<< Should always check if the move moved
rv = new Card(c1.getString(c1.getColumnIndex(DbHandler.NAME)),
c1.getString(c1.getColumnIndex(DbHandler.STREET)),
c1.getString(c1.getColumnIndex(DbHandler.CITY)));
}
c1.close();
return rv; //<<<<< Note should check the returned Card for null
}
public Card querySingleId(字符串szId){
SQLiteDatabase db=getWritableDatabase();
卡rv=空;
游标c1=db.query(表_ADR,szGetTableEntries,_ID+“=?”,新字符串[]{szId},null,null,null);
if(c1.moveToFirst()){//如果您正在重构和改进代码,为什么不直接移动到每个游标,在使用它之后必须关闭它,不再需要它。如果您的方法返回一个游标,您可以在返回它的位置使用它之后关闭它。仅当您确实需要它时才使用列表。我希望将来移动到房间,但目前我不能,因为我需要在运行时和afaik期间创建新表这在room@bytesculptor从技术上讲,您可以在运行时在room中创建表,但在一段时间内,您无法也可能无法做到的是创建关联的类(实体)在运行时构建,您将失去room方法提供的一些优势。您仍然可以使用它们,这可能会有点尴尬。
public Card querySingleId(String szId) {
SQLiteDatabase db = getWritableDatabase();
Cursor c1 = db.query(TABLE_ADR, szGetTableEntries, _ID + " = ?", new String[]{szId}, null, null, null);
c1.moveToFirst();
return new Card(c1.getString(c1.getColumnIndex(DbHandler.NAME)),
c1.getString(c1.getColumnIndex(DbHandler.STREET)),
c1.getString(c1.getColumnIndex(DbHandler.CITY)));
}
public Card querySingleId(String szId) {
SQLiteDatabase db = getWritableDatabase();
Card rv = null;
Cursor c1 = db.query(TABLE_ADR, szGetTableEntries, _ID + " = ?", new String[]{szId}, null, null, null);
if (c1.moveToFirst()) { //<<<<<< Should always check if the move moved
rv = new Card(c1.getString(c1.getColumnIndex(DbHandler.NAME)),
c1.getString(c1.getColumnIndex(DbHandler.STREET)),
c1.getString(c1.getColumnIndex(DbHandler.CITY)));
}
c1.close();
return rv; //<<<<< Note should check the returned Card for null
}