【问题标题】:Sqlite connection Leaked in android studio despite everything is closed尽管一切都已关闭,但 Sqlite 连接在 android studio 中泄漏
【发布时间】:2017-02-20 14:30:31
【问题描述】:

从两天开始,我试图解决我的问题,我参考了这里讨论的每个解决方案,并尽了一切可能,但它仍然继续显示 Sql 连接被泄露。由于此应用程序不稳定,下面是我的 dBhelper 代码。它是一个测验应用程序

private static String DB_NAME = "NavyDb6.db";
private static String DB_PATH = "";
private SQLiteDatabase mDataBase;
private Context mContext = null;

public DbHelper(Context context) {
    super(context, DB_NAME, null, 1);


    DB_PATH = context.getApplicationInfo().dataDir + "/databases/";
    File file = new File(DB_PATH + "NavyDb6.db");
    if (file.exists())
        openDataBase(); // Add this line to fix db.insert can't insert values

    this.mContext = context;
}


public void openDataBase() {
    String myPath = DB_PATH + DB_NAME;
    mDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}

public void copyDataBase() throws IOException {
    try {
        InputStream myInput = mContext.getAssets().open(DB_NAME);
        String outputFileName = DB_PATH + DB_NAME;
        OutputStream myOutput = new FileOutputStream(outputFileName);

        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0)
            myOutput.write(buffer, 0, length);

        myOutput.flush();
        myOutput.close();
        myInput.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private boolean checkDataBase() {
    SQLiteDatabase tempDB = null;
    try {
        String myPath = DB_PATH + DB_NAME;
        tempDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
    } catch (SQLiteException e) {
        e.printStackTrace();
    }
    if (tempDB != null)
        tempDB.close();
    return tempDB != null ? true : false;
}

public void createDataBase() throws IOException {
    boolean isDBExists = checkDataBase();
    if (isDBExists) {

    } else {
        this.getReadableDatabase();
        try {
            copyDataBase();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


}




@Override
public void onCreate(SQLiteDatabase db) {}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}


//We need improve this function to optimize process from Playing
public List<Question> getQuestionMode(String mode) {
    List<Question> listQuestion = new ArrayList<>();
    SQLiteDatabase db = this.getWritableDatabase();
    Cursor c;
    int limit = 0;
    if (mode.equals(Common.MODE.EASY.toString()))
        limit = 20;
    else if (mode.equals(Common.MODE.MEDIUM.toString()))
        limit = 20;
    else if (mode.equals(Common.MODE.HARD.toString()))
        limit = 30;
    else if (mode.equals(Common.MODE.HARDEST.toString()))
        limit = 30;

    try {
        c = db.rawQuery(String.format("SELECT * FROM Question ORDER BY Random() LIMIT %d", limit), null);
        if (c == null) return null;
        c.moveToFirst();
        do {

            int Id = c.getInt(c.getColumnIndex("ID"));
           //int cid= c.getInt(c.getColumnIndex("C_ID"));
            String  Qus = c.getString(c.getColumnIndex("Qus"));
            String AnswerA = c.getString(c.getColumnIndex("AnswerA"));
            String AnswerB = c.getString(c.getColumnIndex("AnswerB"));
            String AnswerC = c.getString(c.getColumnIndex("AnswerC"));
            String AnswerD = c.getString(c.getColumnIndex("AnswerD"));
            String CorrectAnswer = c.getString(c.getColumnIndex("CorrectAnswer"));

            Question question = new Question(Id, Qus, AnswerA, AnswerB, AnswerC, AnswerD, CorrectAnswer);
            listQuestion.add(question);
            db.close();
        }
        while (c.moveToNext());
        c.close();

    } catch (Exception e) {
        e.printStackTrace();
    }
    this.close(); 
    return listQuestion;
}

用于更新分数

public void insertScore(int score) {
    String query = "INSERT INTO Rank(Score) VALUES(" + score + ")";
    mDataBase.execSQL(query);
}


public List<Rank> getRanking() {
    List<Rank> listRanking = new ArrayList<>();
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor c = db.rawQuery("SELECT * FROM Rank Order By Score DESC LIMIT 5;", null);
    try {

        if (c == null) return null;
        c.moveToNext();
        do {
            int Id = c.getInt(c.getColumnIndex("ID"));
            int Score = c.getInt(c.getColumnIndex("Score"));


            Rank ranking = new Rank(Id, Score);
            listRanking.add(ranking);
        } while (c.moveToNext());

    } catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        c.close();
        db.close();
    }
    return listRanking;

}

【问题讨论】:

    标签: android sqlite android-studio memory-leaks android-sqlite


    【解决方案1】:

    您在 getQuestionMode 方法中做错了很多事情。那些是:

    • 读取第一项后关闭数据库连接
    • 在 finally 块外关闭光标

    另外,我会避开这条线if (c == null) return null;

    我建议使用singleton pattern 来访问数据。

    要解决您当前的问题,请尝试以下操作:

    public List<Question> getQuestionMode(String mode) {
        List<Question> listQuestion = new ArrayList<>();
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor c = null;
        int limit = 0;
        if (mode.equals(Common.MODE.EASY.toString()))
            limit = 20;
        else if (mode.equals(Common.MODE.MEDIUM.toString()))
            limit = 20;
        else if (mode.equals(Common.MODE.HARD.toString()))
            limit = 30;
        else if (mode.equals(Common.MODE.HARDEST.toString()))
            limit = 30;
    
        try {
            c = db.rawQuery(String.format("SELECT * FROM Question ORDER BY Random() LIMIT %d", limit), null);
            if(c.moveToFirst()) {
                do {
                    int Id = c.getInt(c.getColumnIndex("ID"));
                   //int cid= c.getInt(c.getColumnIndex("C_ID"));
                    String  Qus = c.getString(c.getColumnIndex("Qus"));
                    String AnswerA = c.getString(c.getColumnIndex("AnswerA"));
                    String AnswerB = c.getString(c.getColumnIndex("AnswerB"));
                    String AnswerC = c.getString(c.getColumnIndex("AnswerC"));
                    String AnswerD = c.getString(c.getColumnIndex("AnswerD"));
                    String CorrectAnswer = c.getString(c.getColumnIndex("CorrectAnswer"));
    
                    Question question = new Question(Id, Qus, AnswerA, AnswerB, AnswerC, AnswerD, CorrectAnswer);
                    listQuestion.add(question);
                  }
                  while (c.moveToNext());
            }
    
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(null != c)
                c.close();
            if(null != db)
                db.close();
        }
    
        return listQuestion;
    }
    

    更新:

    openDataBase() 方法中仍然有一个打开的数据库。还将 finally 块添加到 checkDataBase()

    您可以尝试将您的助手重写为this(参见示例!)。

    【讨论】:

    • 感谢你的时间但我仍然没有工作同样的警告不断显示
    • 2265-2274/com.example.kdeepti.navyquiz D/dalvikvm:GC_FOR_ALLOC 释放 4K,50% 释放 26199K/51616K,暂停 20ms,总共 20ms 2265-2274/com.example.kdeepti.navyquiz W/SQLiteConnectionPool:数据库“xx”的 SQLiteConnection 对象被泄露!请修复您的应用程序以正确结束正在进行的事务并在不再需要时关闭数据库。 2038-2038/com.google.android.gms D/dalvikvm:GC_FOR_ALLOC 释放 699K,释放 25% 的 4863K/6424K,暂停 9ms,总共 9ms
    • 很高兴为您提供帮助 :) 如果您觉得合适,请不要忘记将问题标记为已回答。
    • 我做了更改,它在模拟器中运行良好,现在我尝试在我的手机上运行,​​但应用程序无法运行(强制关闭)..我撤消更改,现在它在移动设备中运行(不稳定形式)。
    • 请在移动设备上显示您的应用程序错误日志。
    猜你喜欢
    • 2013-08-11
    • 2021-07-30
    • 2010-09-19
    • 1970-01-01
    • 2011-06-23
    • 2020-05-13
    • 1970-01-01
    • 2020-06-26
    • 1970-01-01
    相关资源
    最近更新 更多