在返回Cursor的函数中关闭Cursor

时间:2018-05-23 08:22:01

标签: java android android-sqlite

我在SQLite类中关闭Cursor有问题。当我关闭光标并在最后一个块(SQLiteDatabase)中DBHelper时,我无法读取其他类中的数据(无法重新打开关闭的光标错误)但是当我没有关闭Cursor和SQLiteDatabase时,我就会出现内存泄漏错误。

DHHelper.java:

//...
public Cursor selectData(String selectVal, String tabName){
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor c = null;
    try {
        String areaTyp = "SELECT " + selectVal + "  FROM " + tabName;
        c = db.rawQuery(areaTyp, null);
        return c;
    } finally {
        c.close();
        db.close();
    }
}
//...

UserMenager.java

    public List<UserModel> getUsersList(){
    List<UserModel> allUsers = new ArrayList<UserModel>();

    final DBHelper db = new DBHelper(appStatic.CONTEX);
    Cursor c = db.selectData("*","User");
    if (c.moveToFirst()) {
        while (!c.isAfterLast()) {

            allUsers.add(new UserModel(c.getString(c.getColumnIndex("cms_id")),
                    c.getString(c.getColumnIndex("login")),
                            c.getString(c.getColumnIndex("name")),
                                    c.getString(c.getColumnIndex("active")),
                                            c.getString(c.getColumnIndex("avatar")),
                                                    c.getString(c.getColumnIndex("gtoken"))));

            c.moveToNext();
        }
    }
    c.close();
    db.close();

    return allUsers;
}

也许我应该以其他方式执行此操作并且返回Cursor的函数是个坏主意?

修改 当我运行应用程序时,我有错误:

  

java.lang.IllegalStateException:尝试重新打开已经关闭的   object:SQLiteQuery:SELECT * FROM User

在UserMenager.java中,行

if (c.moveToFirst()) {

2 个答案:

答案 0 :(得分:0)

return无法访问后的代码 - 将永远不会被执行。

答案 1 :(得分:0)

我建议从selectData类返回你想要的最终结果,即ArrayList。然后,您可以在selectData方法完成后立即关闭光标和数据库。

e.g。 : -

public ArrayList<UserModel> selectData(String selectVal, String tabName){
    SQLiteDatabase db = this.getWritableDatabase(); //<<<< getReadable will most likely return a writeable database anyway
    ArrayList<UserModel> rv = new ArrayList<>();
    Cursor c = db.query(
            tabName,
            new String[]{selectVal},
            null,
            null,
            null,
            null,
            null
    );
    while (c.moveToNext()) {
        rv.add(new UserModel(
                c.getString(c.getColumnIndex("cms_id")),
                c.getString(c.getColumnIndex("login")),
                c.getString(c.getColumnIndex("name")),
                c.getString(c.getColumnIndex("active")),
                c.getString(c.getColumnIndex("avatar")),
                c.getString(c.getColumnIndex("gtoken"))
        ));
    }
    c.close();
    db.close();
    return rv;
}

同时: -

public List<UserModel> getUsersList(){
    List<UserModel> allUsers = new ArrayList<UserModel>();

    final DBHelper db = new DBHelper(appStatic.CONTEX);
    return selectData("*","Users");
}
  • 围绕SQLiteDatabase方法包装try / catch往往会造成比原本造成的更多挫折和困惑。
  • 一般来说,建议使用方便方法而不是使用rawQueryexecSQL方法(在这种情况下,query是方便的方法)。
  • 理想情况下, selectVal 应该是列的String [],而不仅仅是符合query便捷方法的字符串。
  • 评论getReadableDatabase很少按照
  • 获取只读数据库
  
      
  • 创建和/或打开数据库。这将是getWritableDatabase()返回的相同对象,除非出现一些问题,例如完整磁盘,   要求数据库以只读方式打开。在那种情况下,a   将返回只读数据库对象。如果问题得到解决,a   将来调用getWritableDatabase()可能会成功,在这种情况下   将关闭只读数据库对象和读/写对象   将来会被退回。   SQLiteDatabase getReadableDatabase
  •