如何防止android中的异步任务中的数据库泄漏?

时间:2015-03-19 10:40:32

标签: android sqlite android-fragments

我有一个包含3个标签的主要活动,每个标签包含一个片段。 每个片段都执行异步任务,其中可能发生数据库插入或更新。问题是,如果我在执行异步任务时按下后退按钮,应用程序将关闭并发生数据库泄漏。我想在关闭应用程序之前关闭数据库连接。由于片段没有onBackPressed方法,在这种情况下如何处理数据库?

这是我的异步任务中发生的事件的示例:

@Override
    protected String doInBackground(String... args) {

        SQLiteDatabase db = getActivity().openOrCreateDatabase("myDataBase", SQLiteDatabase.CREATE_IF_NECESSARY, null);

        JSONObject json = jParser.makeHttpRequest(NewsFeedURL, "POST", params);
        if (json != null) {
            try {
                int success = json.getInt(TAG_SUCCESS);
                if (success == 1) {

                    jsonNfArray = json.getJSONArray(TAG_NEWSFEED);

                    for (int i = 0; i < jsonNfArray.length(); i++) {
                        JSONObject nf = jsonNfArray.getJSONObject(i);

                        ContentValues con_val = new ContentValues();
                        con_val.put("nid", nf.getString("nid"));
                        con_val.put("headlines", nf.getString("headlines"));
                        con_val.put("news", nf.getString("news"));
                        con_val.put("date", nf.getString("date"));
                        con_val.put("imgurl", nf.getString("images"));
                        db.insert("newsfeed_tbl", null, con_val);

                        newsfeed_success = true;
                    }
                    db.close();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

2 个答案:

答案 0 :(得分:1)

由于以下原因,您的SQL数据库正在泄漏​​:

1。应用程序正在doInBackground()中执行数据库插入操作

db.insert("newsfeed_tbl", null, con_val);

2. 如果doInBackground()中有任何异常 - >尝试块然后catch块将执行和close语句:

 db.close();

将不会被执行且数据库将保持打开状态

  

所以,作为一个好习惯,我们应该关闭Cursor和   数据库/ DatabaseAdapter实例,在我们的数据库操作之后   完成

解决方案:

@Override
protected String doInBackground(String... args) {


    // database is opened
    SQLiteDatabase db = getActivity().openOrCreateDatabase("myDataBase", SQLiteDatabase.CREATE_IF_NECESSARY, null);

    JSONObject json = jParser.makeHttpRequest(NewsFeedURL, "POST", params);
    if (json != null) {
        try {
            int success = json.getInt(TAG_SUCCESS);
            if (success == 1) {

                jsonNfArray = json.getJSONArray(TAG_NEWSFEED);

                for (int i = 0; i < jsonNfArray.length(); i++) {
                    JSONObject nf = jsonNfArray.getJSONObject(i);

                    ContentValues con_val = new ContentValues();
                    con_val.put("nid", nf.getString("nid"));
                    con_val.put("headlines", nf.getString("headlines"));
                    con_val.put("news", nf.getString("news"));
                    con_val.put("date", nf.getString("date"));
                    con_val.put("imgurl", nf.getString("images"));
                    db.insert("newsfeed_tbl", null, con_val);

                    newsfeed_success = true;
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        } finally {
            // this block will execute in both case
            // case 1: no exception come in doInBackground()
            // case 2: any exception come and caught in doInBackground()
            // this will prevent database leaking
            db.close();
        }
    }
    return null;
}

您可以参考Good Answer关于SQL数据库泄漏异常

答案 1 :(得分:0)

你可以覆盖每个片段上的onDestroy()并将db.close()放在那里。