0

I have a main activity with 3 tabs, each tab containing a fragment. Each fragment does an async task in which database insertions or updations may occur. The problem is, if i press the back button while the async task is executing, the app closes and a database leak occurs. I want the database connection to be closed before closing the app. Since fragments dont have the onBackPressed method, how do i handle the database in this situation?

This is a sample of what happens inside my async task:

@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;
    }
Andro ID
  • 3
  • 3

2 Answers2

1

Your SQL database is leaking because of following reasons :

1. Application is performing database insertion operation in doInBackground()

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

2. If there is any exception in doInBackground() -> try block then catch block will execute and the close statement :

 db.close();

will not be executed and database will remain open which is leaking

So, as a good practice, we should close Cursor and Database/DatabaseAdapter instances, after our database operation are completed

Solution :

@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;
}

You may refer Good Answer regarding SQL database leak exception

Community
  • 1
  • 1
Kushal
  • 8,100
  • 9
  • 63
  • 82
0

You can override onDestroy() on each fragment and put you db.close() in there.

  • 1
    onDestroy() is called only if the activity containing fragment is destroyed by Android system. So, it is not 100% chance that onDestroy() callback will occur. So, check [http://stackoverflow.com/a/29142721/1994950] answer – Kushal Mar 19 '15 at 10:58