使用 Android 的游标从数据库实现方法 getXXX 的最佳实践
Best practice to implement method getXXX from db using cursor for Android
例如下面的示例代码。我们需要关闭游标吗?我们最好使用 try/catch/finally 而不是 if() 吗?
public int getCount() {
final Cursor countCursor = contentResolver.query(
AnalyticContract.CONTENT_URI,
new String[] {"count(*) AS count"},
null,
null,
null);
if (countCursor == null) {
return 0;
}
countCursor.moveToFirst();
final int count = countCursor.getInt(0);
return count;
}
try-with-resources语句是声明一个或多个资源的try语句。资源是一个对象,在程序使用完它后必须关闭。 try-with-resources 语句确保在语句结束时关闭每个资源。任何实现 java.lang.AutoCloseable 的对象,包括所有实现 java.io.Closeable 的对象,都可以用作资源。
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
我认为答案主要是基于意见的。我猜这取决于编码人员的偏好和环境。
我一直更喜欢 if (cursor != null)
方法,反之亦然。除非发生了真正壮观的事情;这将由 throws Exception
处理,我会在任何我想要 reader/reviewer 的地方使用 if-else 检查来查看哪些部分是 真正的 异常,哪些是出现不同的 possible/valid 情景。
这给我们带来了 Curosr
和应用空值检查的当前问题。
AFAIK(因为大多数 Cursor
与 SQLiteDatabase
相关)如果查询本身是有效,除非在无效查询的情况下这是一个真正的异常,你应该得到一个异常。
所以我认为最好的方法是使用您的示例
public int getCount() throws Exception {
Cursor countCursor;
try {
countCursor = contentResolver.query(
AnalyticContract.CONTENT_URI,
new String[] {"count(*) AS count"},
null,
null,
null);
countCursor.moveToFirst();
return countCursor.getInt(0);
}
finally {
cursor.close();
}
}
或者在方法本身内捕获和处理异常的变体。
现在回答你的第二个问题,你是否应该 close()
a Cursor
:你应该总是关闭 a Cursor
。当你不需要它的时候。如果您深入研究任何 Cursor.close()
方法实现。由于 Curosr
是一个接口,如果 SQLite 是由 SQLiteCursor
实现的,您会注意到此方法释放了它持有的所有分配。
我更喜欢做一个数据库助手class,这样数据库访问就变得容易多了。数据库助手示例 Class -
public class DatabaseHelperClass extends SQLiteOpenHelper {
public DatabaseHelperClass(Context context)
{
super(context,"hakeem.db",null,1);
}
//Tables
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("Your SQL Query to create a table");
}
//Delete Tables
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table table_name if exists");
onCreate(db);
}
//Insertion of data into tables
long insertData(Various Parameters you like to pass for insertion)
{
SQLiteDatabase db=getWritableDatabase();
ContentValues values=new ContentValues();
values.put("col_name1",value);
values.put("col_name2",value);
values.put("col_name3",value);
values.put("col_name4",value);
return db.insert("signup_details",null,values);
}
//Delete record
public int deleteData(int id)
{
SQLiteDatabase sb=getWritableDatabase();
return sb.delete("hospital_details","id="+id,null);
}
//Update data in table
int updateData(Parameters you want to pass for update. Make sure you include a primary key)
{
ContentValues values=new ContentValues();
values.put("col_name1",value);
values.put("col_name2",value);
values.put("col_name3",value);
values.put("col_name4",value);
return getWritableDatabase().update("signup_details",values,"id="+id,null);
}
//Read data from tables
Cursor getSigninDetails() { return getWritableDatabase().rawQuery("select * from table_name",null); }
}
并从数据库访问结果-
private void getDataFromDatabase() {
Cursor cursor = db.getUserData();
if (cursor.moveToFirst()) {
do {
var_name1= cursor.getString(0);
var_name2= cursor.getString(1);
var_name3= cursor.getString(2);
var_name4= cursor.getString(3);
} while (cursor.moveToNext());
}
cursor.close();
}
例如下面的示例代码。我们需要关闭游标吗?我们最好使用 try/catch/finally 而不是 if() 吗?
public int getCount() {
final Cursor countCursor = contentResolver.query(
AnalyticContract.CONTENT_URI,
new String[] {"count(*) AS count"},
null,
null,
null);
if (countCursor == null) {
return 0;
}
countCursor.moveToFirst();
final int count = countCursor.getInt(0);
return count;
}
try-with-resources语句是声明一个或多个资源的try语句。资源是一个对象,在程序使用完它后必须关闭。 try-with-resources 语句确保在语句结束时关闭每个资源。任何实现 java.lang.AutoCloseable 的对象,包括所有实现 java.io.Closeable 的对象,都可以用作资源。 https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
我认为答案主要是基于意见的。我猜这取决于编码人员的偏好和环境。
我一直更喜欢 if (cursor != null)
方法,反之亦然。除非发生了真正壮观的事情;这将由 throws Exception
处理,我会在任何我想要 reader/reviewer 的地方使用 if-else 检查来查看哪些部分是 真正的 异常,哪些是出现不同的 possible/valid 情景。
这给我们带来了 Curosr
和应用空值检查的当前问题。
AFAIK(因为大多数 Cursor
与 SQLiteDatabase
相关)如果查询本身是有效,除非在无效查询的情况下这是一个真正的异常,你应该得到一个异常。
所以我认为最好的方法是使用您的示例
public int getCount() throws Exception {
Cursor countCursor;
try {
countCursor = contentResolver.query(
AnalyticContract.CONTENT_URI,
new String[] {"count(*) AS count"},
null,
null,
null);
countCursor.moveToFirst();
return countCursor.getInt(0);
}
finally {
cursor.close();
}
}
或者在方法本身内捕获和处理异常的变体。
现在回答你的第二个问题,你是否应该 close()
a Cursor
:你应该总是关闭 a Cursor
。当你不需要它的时候。如果您深入研究任何 Cursor.close()
方法实现。由于 Curosr
是一个接口,如果 SQLite 是由 SQLiteCursor
实现的,您会注意到此方法释放了它持有的所有分配。
我更喜欢做一个数据库助手class,这样数据库访问就变得容易多了。数据库助手示例 Class -
public class DatabaseHelperClass extends SQLiteOpenHelper {
public DatabaseHelperClass(Context context)
{
super(context,"hakeem.db",null,1);
}
//Tables
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("Your SQL Query to create a table");
}
//Delete Tables
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("drop table table_name if exists");
onCreate(db);
}
//Insertion of data into tables
long insertData(Various Parameters you like to pass for insertion)
{
SQLiteDatabase db=getWritableDatabase();
ContentValues values=new ContentValues();
values.put("col_name1",value);
values.put("col_name2",value);
values.put("col_name3",value);
values.put("col_name4",value);
return db.insert("signup_details",null,values);
}
//Delete record
public int deleteData(int id)
{
SQLiteDatabase sb=getWritableDatabase();
return sb.delete("hospital_details","id="+id,null);
}
//Update data in table
int updateData(Parameters you want to pass for update. Make sure you include a primary key)
{
ContentValues values=new ContentValues();
values.put("col_name1",value);
values.put("col_name2",value);
values.put("col_name3",value);
values.put("col_name4",value);
return getWritableDatabase().update("signup_details",values,"id="+id,null);
}
//Read data from tables
Cursor getSigninDetails() { return getWritableDatabase().rawQuery("select * from table_name",null); }
}
并从数据库访问结果-
private void getDataFromDatabase() {
Cursor cursor = db.getUserData();
if (cursor.moveToFirst()) {
do {
var_name1= cursor.getString(0);
var_name2= cursor.getString(1);
var_name3= cursor.getString(2);
var_name4= cursor.getString(3);
} while (cursor.moveToNext());
}
cursor.close();
}