简体   繁体   中英

Is there an effective way to refactor this Android SQLite database handler?

I'm working on my first Android application and I've run into an issue where I'm reusing alot of code snippets to perform the db-connectivity. I see myself rewriting the same try/catch statements over and over again but I'm having issues seeing a good way to handle it. Please have a look at this code, do you see any obvious way that I am missing on how to refactor this?

As you can see there is often only 1 or 2 line difference in the methods. Here's an example (all the other try/catch code is similar):

Cursor cursor = dbAdapter.fetchReceipts(timeFrom, timeTo);

Communicator.java

    public ArrayList<Receipt> getReceipts(int limit)
{
    ArrayList<Receipt> receiptList = null;
    DbAdapter dbAdapter = new DbAdapter(context);

    try
    {
        dbAdapter.open();
        Cursor cursor = dbAdapter.fetchReceipts(limit);

        if (cursor != null)
        {
            receiptList = buildReceiptList(cursor);
        }

        dbAdapter.close();
    }
    catch (SQLException e)
    {
        Log.d(context.getString(R.string.tag_receipttracker), e.getMessage());
        showToast(MESSAGE_COULD_NOT_OPEN);
    }
    return receiptList;
}

public ArrayList<Receipt> getReceipts(long timeFrom, long timeTo)
{
    ArrayList<Receipt> receiptList = null;
    DbAdapter dbAdapter = new DbAdapter(context);

    try
    {
        dbAdapter.open();
        Cursor cursor = dbAdapter.fetchReceipts(timeFrom, timeTo);

        if (cursor != null)
        {
            receiptList = buildReceiptList(cursor);
        }

        dbAdapter.close();
    }
    catch (SQLException e)
    {
        Log.d(context.getString(R.string.tag_receipttracker), e.getMessage());
        showToast(MESSAGE_COULD_NOT_OPEN);
    }
    return receiptList;
}


public Receipt getLatestReceipt()
{
    Receipt receipt = null;
    Cursor cursor = null;
    DbAdapter dbAdapter = new DbAdapter(context);

    try
    {
        dbAdapter.open();
        cursor = dbAdapter.fetchLastReceipt();

        if (cursor.getCount() > 0)
        {
            receipt = buildReceipt(cursor);
        }

        dbAdapter.close();
    }
    catch (SQLException e)
    {
        Log.d(context.getString(R.string.tag_receipttracker), e.getMessage());
        showToast(MESSAGE_COULD_NOT_OPEN);
    }
    return receipt;
}

public ArrayList<Receipt> searchReceipts(String query)
{
    ArrayList<Receipt> receiptList = null;
    DbAdapter dbAdapter = new DbAdapter(context);

    try
    {
        dbAdapter.open();
        Cursor cursor = dbAdapter.searchReceiptName(query);

        if (cursor != null)
        {
            receiptList = buildReceiptList(cursor);
        }

        dbAdapter.close();
    }
    catch (SQLException e)
    {
        Log.d(context.getString(R.string.tag_receipttracker), e.getMessage());
        showToast(MESSAGE_COULD_NOT_OPEN);
    }

    return receiptList;
}

public boolean updateReceipt(Receipt receipt)
{
    DbAdapter dbAdapter = new DbAdapter(context);
    boolean result = false;
    try
    {
        dbAdapter.open();
        result = dbAdapter.updateReceipt(receipt.getId(), receipt.getName(), receipt.getPhoto(), receipt.getTimestamp(),
                receipt.getLocationLat(), receipt.getLocationLong(), receipt.getSum(), receipt.getTax(), receipt.getComment());
        showResult(result);
        dbAdapter.close();
    }
    catch (SQLException e)
    {
        Log.d(context.getString(R.string.tag_receipttracker), e.getMessage());
        showToast(MESSAGE_COULD_NOT_OPEN);
    }
    return result;
}

private boolean insertReceipt(Receipt receipt)
{
    boolean result = false;
    DbAdapter dbAdapter = new DbAdapter(context);
    try
    {
        dbAdapter.open();
        result = dbAdapter.createReceipt(receipt.getName(), receipt.getPhoto(), receipt.getTimestamp(), receipt.getLocationLat(),
                receipt.getLocationLong(), receipt.getSum(), receipt.getTax(), receipt.getComment());
        showResult(result);
        dbAdapter.close();
    }
    catch (SQLException e)
    {
        Log.d(context.getString(R.string.tag_receipttracker), e.getMessage());
        showToast(MESSAGE_COULD_NOT_OPEN);
    }
    return result;
}

DBAdapter.java

public Cursor fetchReceipt(long rowId) throws SQLException
{

    Cursor cursor = db
            .query(true, DATABASE_TABLE_RECEIPTS, new String[] { KEY_ROWID, KEY_NAME, KEY_PHOTO, KEY_TIMESTAMP, KEY_LOCATION_LAT,
                    KEY_LOCATION_LONG, KEY_SUM, KEY_TAX, KEY_COMMENT }, KEY_ROWID + "=" + rowId, null, null, null, null, null);
    if (cursor != null)
    {
        cursor.moveToFirst();
    }
    return cursor;

}

public Cursor fetchReceipts(long timeFrom, long timeTo)
{
    Cursor cursor = db.query(true, DATABASE_TABLE_RECEIPTS, new String[] { KEY_ROWID, KEY_NAME, KEY_PHOTO, KEY_TIMESTAMP,
            KEY_LOCATION_LAT, KEY_LOCATION_LONG, KEY_SUM, KEY_TAX, KEY_COMMENT }, KEY_TIMESTAMP + ">" + timeFrom + " AND "
            + KEY_TIMESTAMP + "<" + timeTo, null, null, null, KEY_TIMESTAMP + " DESC", null);
    if (cursor != null)
    {
        cursor.moveToFirst();
    }
    return cursor;
}

public Cursor fetchLastReceipt()
{
    Cursor cursor = db.query(true, DATABASE_TABLE_RECEIPTS, new String[] { KEY_ROWID, KEY_NAME, KEY_PHOTO, KEY_TIMESTAMP,
            KEY_LOCATION_LAT, KEY_LOCATION_LONG, KEY_SUM, KEY_TAX, KEY_COMMENT }, null, null, null, null, KEY_ROWID + " DESC", "1");
    if (cursor != null)
    {
        cursor.moveToFirst();
    }
    return cursor;
}

public Cursor searchReceiptName(String query)
    {
        Cursor cursor = db.query(DATABASE_TABLE_RECEIPTS, new String[] { KEY_ROWID, KEY_NAME, KEY_PHOTO, KEY_TIMESTAMP, KEY_LOCATION_LAT,
                KEY_LOCATION_LONG, KEY_SUM, KEY_TAX, KEY_COMMENT }, KEY_NAME + " LIKE ?", new String[] { "%" + query + "%" }, null, null,
                null);
        if (cursor != null)
        {
            cursor.moveToFirst();
        }
        return cursor;
    }

First of all when opening the db, I'd better use something like this:

if (db == null || !db.isOpen()) {
db = getWritableDatabase(); //getReadableDatabase();
}

which takes care for you to either create or open the database in case it is not yet done.

For the first block of methods I'd clearly go for somethink like:

public ArrayList<Receipt> searchReceipts(String query, DbAdapter _db, Cursor cursor)
{
    ArrayList<Receipt> receiptList = null;

    try
    {
        _db.open();

        if (cursor != null)
        {
            receiptList = buildReceiptList(cursor);
        }

        _db.close();
    }
    catch (SQLException e)
    {
        Log.d(context.getString(R.string.tag_receipttracker), e.getMessage());
        showToast(MESSAGE_COULD_NOT_OPEN);
    }

    return receiptList;
}

This way you'll just need to previously create the adapter and the cursor and pass them along in that main method that will perform the rest of the logic for all the calls. I noticed there's one method in which you just return an object instead of an array. In this case you could just pass an array with a sole object inside.

Hope it helps.

Let me know about your impressions / updates.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM