From 6c58c1072c9af6ea0d0f52baeae7f95ba7f7ee2f Mon Sep 17 00:00:00 2001 From: Damyan Ivanov Date: Sun, 16 Dec 2018 17:07:44 +0000 Subject: [PATCH 1/1] move DB stuff into a static class downside is that we need to pass a context around --- .../net/ktnx/mobileledger/AccountSummary.java | 15 +- .../mobileledger/AccountSummaryViewModel.java | 16 +- .../mobileledger/NewTransactionActivity.java | 14 +- .../mobileledger/TransactionListActivity.java | 12 +- .../mobileledger/TransactionListAdapter.java | 7 +- .../async/RetrieveAccountsTask.java | 5 +- .../async/RetrieveTransactionsTask.java | 5 +- .../TransactionListViewModel.java | 11 +- .../{MobileLedgerDatabase.java => MLDB.java} | 157 ++++++++++-------- 9 files changed, 120 insertions(+), 122 deletions(-) rename app/src/main/java/net/ktnx/mobileledger/utils/{MobileLedgerDatabase.java => MLDB.java} (60%) diff --git a/app/src/main/java/net/ktnx/mobileledger/AccountSummary.java b/app/src/main/java/net/ktnx/mobileledger/AccountSummary.java index 5ad2a57d..2c9589e3 100644 --- a/app/src/main/java/net/ktnx/mobileledger/AccountSummary.java +++ b/app/src/main/java/net/ktnx/mobileledger/AccountSummary.java @@ -43,7 +43,7 @@ import android.widget.LinearLayout; import net.ktnx.mobileledger.async.RetrieveAccountsTask; import net.ktnx.mobileledger.model.LedgerAccount; -import net.ktnx.mobileledger.utils.MobileLedgerDatabase; +import net.ktnx.mobileledger.utils.MLDB; import java.lang.ref.WeakReference; import java.util.Date; @@ -58,7 +58,6 @@ public class AccountSummary extends AppCompatActivity { private static boolean account_list_needs_update = true; MenuItem mShowHiddenAccounts; SharedPreferences.OnSharedPreferenceChangeListener sBindPreferenceSummaryToValueListener; - private MobileLedgerDatabase dbh; private AccountSummaryViewModel model; private AccountSummaryAdapter modelAdapter; private Menu optMenu; @@ -74,8 +73,6 @@ public class AccountSummary extends AppCompatActivity { Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); - dbh = new MobileLedgerDatabase(this); - drawer = findViewById(R.id.drawer_layout); ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); @@ -92,7 +89,7 @@ public class AccountSummary extends AppCompatActivity { } model = ViewModelProviders.of(this).get(AccountSummaryViewModel.class); - List accounts = model.getAccounts(); + List accounts = model.getAccounts(getApplicationContext()); modelAdapter = new AccountSummaryAdapter(accounts); RecyclerView root = findViewById(R.id.account_root); @@ -250,7 +247,7 @@ public class AccountSummary extends AppCompatActivity { } private void prepare_db() { - account_list_last_updated = dbh.get_option_value("last_refresh", (long) 0); + account_list_last_updated = MLDB.get_option_value(this, "last_refresh", (long) 0); } private void update_accounts(boolean force) { @@ -277,12 +274,12 @@ public class AccountSummary extends AppCompatActivity { Snackbar.make(drawer, err_text, Snackbar.LENGTH_LONG ).show(); } else { - dbh.set_option_value("last_refresh", new Date().getTime() ); + MLDB.set_option_value(this, "last_refresh", new Date().getTime()); update_account_table(); } } private void update_account_table() { - model.reloadAccounts(); + model.reloadAccounts(getApplicationContext()); modelAdapter.notifyDataSetChanged(); } void stopSelection() { @@ -301,7 +298,7 @@ public class AccountSummary extends AppCompatActivity { stopSelection(); } public void onConfirmAccSelection(MenuItem item) { - model.commitSelections(); + model.commitSelections(getApplicationContext()); stopSelection(); } } diff --git a/app/src/main/java/net/ktnx/mobileledger/AccountSummaryViewModel.java b/app/src/main/java/net/ktnx/mobileledger/AccountSummaryViewModel.java index f01907b3..f9b5d74f 100644 --- a/app/src/main/java/net/ktnx/mobileledger/AccountSummaryViewModel.java +++ b/app/src/main/java/net/ktnx/mobileledger/AccountSummaryViewModel.java @@ -37,7 +37,7 @@ import android.widget.LinearLayout; import android.widget.TextView; import net.ktnx.mobileledger.model.LedgerAccount; -import net.ktnx.mobileledger.utils.MobileLedgerDatabase; +import net.ktnx.mobileledger.utils.MLDB; import java.util.ArrayList; import java.util.List; @@ -45,24 +45,22 @@ import java.util.List; import static net.ktnx.mobileledger.SettingsActivity.PREF_KEY_SHOW_ONLY_STARRED_ACCOUNTS; class AccountSummaryViewModel extends AndroidViewModel { - private MobileLedgerDatabase dbh; private List accounts; public AccountSummaryViewModel(@NonNull Application application) { super(application); - dbh = new MobileLedgerDatabase(application); } - List getAccounts() { + List getAccounts(Context context) { if (accounts == null) { accounts = new ArrayList<>(); - reloadAccounts(); + reloadAccounts(context); } return accounts; } - void reloadAccounts() { + void reloadAccounts(Context context) { accounts.clear(); boolean showingOnlyStarred = PreferenceManager.getDefaultSharedPreferences(getApplication()) @@ -71,7 +69,7 @@ class AccountSummaryViewModel extends AndroidViewModel { if (showingOnlyStarred) sql += " WHERE hidden = 0"; sql += " ORDER BY name"; - try (SQLiteDatabase db = dbh.getReadableDatabase()) { + try (SQLiteDatabase db = MLDB.getReadableDatabase(context)) { try (Cursor cursor = db .rawQuery(sql,null)) { @@ -91,8 +89,8 @@ class AccountSummaryViewModel extends AndroidViewModel { } } } - void commitSelections() { - try(SQLiteDatabase db = dbh.getWritableDatabase()) { + void commitSelections(Context context) { + try(SQLiteDatabase db = MLDB.getWritableDatabase(context)) { db.beginTransaction(); try { for (LedgerAccount acc : accounts) { diff --git a/app/src/main/java/net/ktnx/mobileledger/NewTransactionActivity.java b/app/src/main/java/net/ktnx/mobileledger/NewTransactionActivity.java index 4950a1ef..38289020 100644 --- a/app/src/main/java/net/ktnx/mobileledger/NewTransactionActivity.java +++ b/app/src/main/java/net/ktnx/mobileledger/NewTransactionActivity.java @@ -56,7 +56,7 @@ import net.ktnx.mobileledger.async.TaskCallback; import net.ktnx.mobileledger.model.LedgerTransaction; import net.ktnx.mobileledger.model.LedgerTransactionItem; import net.ktnx.mobileledger.ui.DatePickerFragment; -import net.ktnx.mobileledger.utils.MobileLedgerDatabase; +import net.ktnx.mobileledger.utils.MLDB; import java.util.Date; import java.util.Objects; @@ -80,7 +80,6 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal private AutoCompleteTextView text_descr; private static SaveTransactionTask saver; private MenuItem mSave; - private MobileLedgerDatabase dbh; @Override protected void onCreate(Bundle savedInstanceState) { @@ -89,8 +88,6 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); - dbh = new MobileLedgerDatabase(this); - text_date = findViewById(R.id.new_transaction_date); text_date.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override @@ -100,8 +97,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal } }); text_descr = findViewById(R.id.new_transaction_description); - hook_autocompletion_adapter(text_descr, MobileLedgerDatabase - .DESCRIPTION_HISTORY_TABLE, "description"); + hook_autocompletion_adapter(text_descr, MLDB.DESCRIPTION_HISTORY_TABLE, "description"); hook_text_change_listener(text_descr); progress = findViewById(R.id.save_transaction_progress); @@ -113,7 +109,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal AutoCompleteTextView acc_name_view = (AutoCompleteTextView) row.getChildAt(0); TextView amount_view = (TextView) row.getChildAt(1); hook_swipe_listener(row); - hook_autocompletion_adapter(acc_name_view, MobileLedgerDatabase.ACCOUNTS_TABLE, "name"); + hook_autocompletion_adapter(acc_name_view, MLDB.ACCOUNTS_TABLE, "name"); hook_text_change_listener(acc_name_view); hook_text_change_listener(amount_view); // Log.d("swipe", "hooked to row "+i); @@ -270,7 +266,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal String[] col_names = {FontsContract.Columns._ID, field}; MatrixCursor c = new MatrixCursor(col_names); - try (SQLiteDatabase db = dbh.getReadableDatabase()) { + try (SQLiteDatabase db = MLDB.getReadableDatabase(getApplicationContext())) { try (Cursor matches = db.rawQuery(String.format( "SELECT %s as a, case when %s_upper LIKE ?||'%%' then 1 " @@ -358,7 +354,7 @@ public class NewTransactionActivity extends AppCompatActivity implements TaskCal if (focus) acc.requestFocus(); hook_swipe_listener(row); - hook_autocompletion_adapter(acc, MobileLedgerDatabase.ACCOUNTS_TABLE, "name"); + hook_autocompletion_adapter(acc, MLDB.ACCOUNTS_TABLE, "name"); hook_text_change_listener(acc); hook_text_change_listener(amt); } diff --git a/app/src/main/java/net/ktnx/mobileledger/TransactionListActivity.java b/app/src/main/java/net/ktnx/mobileledger/TransactionListActivity.java index 1073909d..715af08a 100644 --- a/app/src/main/java/net/ktnx/mobileledger/TransactionListActivity.java +++ b/app/src/main/java/net/ktnx/mobileledger/TransactionListActivity.java @@ -35,7 +35,7 @@ import android.widget.TextView; import net.ktnx.mobileledger.async.RetrieveTransactionsTask; import net.ktnx.mobileledger.model.LedgerTransaction; import net.ktnx.mobileledger.ui.transaction_list.TransactionListViewModel; -import net.ktnx.mobileledger.utils.MobileLedgerDatabase; +import net.ktnx.mobileledger.utils.MLDB; import java.lang.ref.WeakReference; import java.time.ZoneId; @@ -60,8 +60,6 @@ public class TransactionListActivity extends AppCompatActivity { setupActionBar(); - MobileLedgerDatabase dbh = new MobileLedgerDatabase(this); - swiper = findViewById(R.id.transaction_swipe); if (swiper == null) throw new RuntimeException("Can't get hold on the swipe layout"); root = findViewById(R.id.transaction_root); @@ -71,7 +69,7 @@ public class TransactionListActivity extends AppCompatActivity { throw new RuntimeException("Can't get hold on the transaction list progress bar"); tvLastUpdate = findViewById(R.id.transactions_last_update); { - long last_update = dbh.get_option_value("transaction_list_last_update", 0L); + long last_update = MLDB.get_option_value(this, "transaction_list_last_update", 0L); Log.d("transactions", String.format("Last update = %d", last_update)); if (last_update == 0) tvLastUpdate.setText("never"); else { @@ -86,7 +84,7 @@ public class TransactionListActivity extends AppCompatActivity { } } model = ViewModelProviders.of(this).get(TransactionListViewModel.class); - List transactions = model.getTransactions(dbh); + List transactions = model.getTransactions(getApplicationContext()); modelAdapter = new TransactionListAdapter(transactions); RecyclerView root = findViewById(R.id.transaction_root); @@ -157,9 +155,9 @@ public class TransactionListActivity extends AppCompatActivity { progressBar.setVisibility(View.GONE); swiper.setRefreshing(false); if (success) { - MobileLedgerDatabase dbh = new MobileLedgerDatabase(this); Date now = new Date(); - dbh.set_option_value("transaction_list_last_update", now.getTime()); + MLDB.set_option_value(getApplicationContext(), "transaction_list_last_update", + now.getTime()); updateLastUpdateText(now); modelAdapter.notifyDataSetChanged(); } diff --git a/app/src/main/java/net/ktnx/mobileledger/TransactionListAdapter.java b/app/src/main/java/net/ktnx/mobileledger/TransactionListAdapter.java index b82e84ca..d0b2e943 100644 --- a/app/src/main/java/net/ktnx/mobileledger/TransactionListAdapter.java +++ b/app/src/main/java/net/ktnx/mobileledger/TransactionListAdapter.java @@ -33,7 +33,7 @@ import android.widget.TextView; import net.ktnx.mobileledger.model.LedgerTransaction; import net.ktnx.mobileledger.model.LedgerTransactionItem; -import net.ktnx.mobileledger.utils.MobileLedgerDatabase; +import net.ktnx.mobileledger.utils.MLDB; import java.util.Iterator; import java.util.List; @@ -50,9 +50,8 @@ class TransactionListAdapter LedgerTransaction tr = transactions.get(position); Context ctx = holder.row.getContext(); Resources rm = ctx.getResources(); - try (MobileLedgerDatabase dbh = new MobileLedgerDatabase(ctx)) { - try (SQLiteDatabase db = dbh.getReadableDatabase()) { - tr.loadData(db); + try (SQLiteDatabase db = MLDB.getReadableDatabase(ctx.getApplicationContext())) { + tr.loadData(db); holder.tvDescription .setText(String.format("%s\n%s", tr.getDescription(), tr.getDate())); diff --git a/app/src/main/java/net/ktnx/mobileledger/async/RetrieveAccountsTask.java b/app/src/main/java/net/ktnx/mobileledger/async/RetrieveAccountsTask.java index 8117a198..3d96d327 100644 --- a/app/src/main/java/net/ktnx/mobileledger/async/RetrieveAccountsTask.java +++ b/app/src/main/java/net/ktnx/mobileledger/async/RetrieveAccountsTask.java @@ -24,7 +24,7 @@ import android.util.Log; import net.ktnx.mobileledger.AccountSummary; import net.ktnx.mobileledger.R; import net.ktnx.mobileledger.model.LedgerAccount; -import net.ktnx.mobileledger.utils.MobileLedgerDatabase; +import net.ktnx.mobileledger.utils.MLDB; import net.ktnx.mobileledger.utils.NetworkUtil; import java.io.BufferedReader; @@ -58,8 +58,7 @@ public class RetrieveAccountsTask extends android.os.AsyncTask transactions; - public List getTransactions(MobileLedgerDatabase dbh) { + public List getTransactions(Context context) { if (transactions == null) { transactions = new ArrayList<>(); - reloadTransactions(dbh); + reloadTransactions(context); } return transactions; } - private void reloadTransactions(MobileLedgerDatabase dbh) { + private void reloadTransactions(Context context) { transactions.clear(); String sql = "SELECT id FROM transactions ORDER BY date desc, id desc"; - try (SQLiteDatabase db = dbh.getReadableDatabase()) { + try (SQLiteDatabase db = MLDB.getReadableDatabase(context)) { try (Cursor cursor = db.rawQuery(sql, null)) { while (cursor.moveToNext()) { transactions.add(new LedgerTransaction(cursor.getInt(0))); diff --git a/app/src/main/java/net/ktnx/mobileledger/utils/MobileLedgerDatabase.java b/app/src/main/java/net/ktnx/mobileledger/utils/MLDB.java similarity index 60% rename from app/src/main/java/net/ktnx/mobileledger/utils/MobileLedgerDatabase.java rename to app/src/main/java/net/ktnx/mobileledger/utils/MLDB.java index 7efc0ae8..5fd4e0e6 100644 --- a/app/src/main/java/net/ktnx/mobileledger/utils/MobileLedgerDatabase.java +++ b/app/src/main/java/net/ktnx/mobileledger/utils/MLDB.java @@ -31,89 +31,56 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.Locale; -public class MobileLedgerDatabase extends SQLiteOpenHelper implements AutoCloseable { - public static final String DB_NAME = "mobile-ledger.db"; +import static net.ktnx.mobileledger.utils.MLDB.DatabaseMode.READ; +import static net.ktnx.mobileledger.utils.MLDB.DatabaseMode.WRITE; + +public final class MLDB { + public enum DatabaseMode { READ, WRITE }; public static final String ACCOUNTS_TABLE = "accounts"; public static final String DESCRIPTION_HISTORY_TABLE = "description_history"; - public static final int LATEST_REVISION = 8; - - private final Context mContext; - - public - MobileLedgerDatabase(Context context) { - super(context, DB_NAME, null, LATEST_REVISION); - Log.d("db", "creating helper instance"); - mContext = context; - } - - @Override - public - void onCreate(SQLiteDatabase db) { - Log.d("db", "onCreate called"); - onUpgrade(db, -1, LATEST_REVISION); - } - - @Override - public - void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.d("db", "onUpgrade called"); - for(int i = oldVersion+1; i <= newVersion; i++) applyRevision(db, i); - } - - private void applyRevision(SQLiteDatabase db, int - rev_no) { - final Resources rm = mContext.getResources(); - String rev_file = String.format(Locale.US, "sql_%d", rev_no); + private static MobileLedgerDatabase helperForReading, helperForWriting; - int res_id = rm.getIdentifier(rev_file, "raw", mContext.getPackageName()); - if (res_id == 0) - throw new SQLException(String.format(Locale.US, "No resource for revision %d", rev_no)); - db.beginTransaction(); - try (InputStream res = rm.openRawResource(res_id)) { - Log.d("db", "Applying revision " + String.valueOf(rev_no)); - InputStreamReader isr = new InputStreamReader(res); - BufferedReader reader = new BufferedReader(isr); - - String line; - while ((line = reader.readLine()) != null) { - db.execSQL(line); - } - - db.setTransactionSuccessful(); + public static synchronized SQLiteDatabase getDatabase(Context context, DatabaseMode mode) { + if (mode == READ) { + if (helperForReading == null) helperForReading = new MobileLedgerDatabase(context); + return helperForReading.getReadableDatabase(); } - catch (IOException e) { - Log.e("db", String.format("Error opening raw resource for revision %d", rev_no)); - e.printStackTrace(); - } - finally { - db.endTransaction(); + else { + if (helperForWriting == null) helperForWriting = new MobileLedgerDatabase(context); + return helperForWriting.getWritableDatabase(); } } - public int get_option_value(String name, int default_value) { - String s = get_option_value(name, String.valueOf(default_value)); + public static SQLiteDatabase getReadableDatabase(Context context) { + return getDatabase(context, READ); + } + public static SQLiteDatabase getWritableDatabase(Context context) { + return getDatabase(context, WRITE); + } + static public int get_option_value(Context context, String name, int default_value) { + String s = get_option_value(context, name, String.valueOf(default_value)); try { return Integer.parseInt(s); } catch (Exception e) { - Log.d("db", "returning default int value of "+name, e); + Log.d("db", "returning default int value of " + name, e); return default_value; } } - public long get_option_value(String name, long default_value) { - String s = get_option_value(name, String.valueOf(default_value)); + static public long get_option_value(Context context, String name, long default_value) { + String s = get_option_value(context, name, String.valueOf(default_value)); try { return Long.parseLong(s); } catch (Exception e) { - Log.d("db", "returning default long value of "+name, e); + Log.d("db", "returning default long value of " + name, e); return default_value; } } - public String get_option_value(String name, String default_value) { - Log.d("db", "about to fetch option "+name); - try(SQLiteDatabase db = getReadableDatabase()) { + static public String get_option_value(Context context, String name, String default_value) { + Log.d("db", "about to fetch option " + name); + try (SQLiteDatabase db = getReadableDatabase(context)) { try (Cursor cursor = db .rawQuery("select value from options where name=?", new String[]{name})) { @@ -134,25 +101,69 @@ public class MobileLedgerDatabase extends SQLiteOpenHelper implements AutoClosea } } - public void set_option_value(String name, String value) { - Log.d("db", "setting option "+name+"="+value); - try(SQLiteDatabase db = getWritableDatabase()) { + static public void set_option_value(Context context, String name, String value) { + Log.d("db", "setting option " + name + "=" + value); + try (SQLiteDatabase db = getWritableDatabase(context)) { db.execSQL("insert or replace into options(name, value) values(?, ?);", new String[]{name, value}); } } - public void set_option_value(String name, long value) { - set_option_value(name, String.valueOf(value)); + static public void set_option_value(Context context, String name, long value) { + set_option_value(context, name, String.valueOf(value)); } - public static long get_option_value(Context context, String name, long default_value) { - try(MobileLedgerDatabase db = new MobileLedgerDatabase(context)) { - return db.get_option_value(name, default_value); - } +} + +class MobileLedgerDatabase extends SQLiteOpenHelper implements AutoCloseable { + public static final String DB_NAME = "mobile-ledger.db"; + public static final int LATEST_REVISION = 8; + + private final Context mContext; + + public MobileLedgerDatabase(Context context) { + super(context, DB_NAME, null, LATEST_REVISION); + Log.d("db", "creating helper instance"); + mContext = context; + } + + @Override + public void onCreate(SQLiteDatabase db) { + Log.d("db", "onCreate called"); + onUpgrade(db, -1, LATEST_REVISION); } - public static void set_option_value(Context context, String name, String value) { - try(MobileLedgerDatabase db = new MobileLedgerDatabase(context)) { - db.set_option_value(name, value); + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + Log.d("db", "onUpgrade called"); + for (int i = oldVersion + 1; i <= newVersion; i++) applyRevision(db, i); + } + + private void applyRevision(SQLiteDatabase db, int rev_no) { + final Resources rm = mContext.getResources(); + String rev_file = String.format(Locale.US, "sql_%d", rev_no); + + int res_id = rm.getIdentifier(rev_file, "raw", mContext.getPackageName()); + if (res_id == 0) throw new SQLException( + String.format(Locale.US, "No resource for revision %d", rev_no)); + db.beginTransaction(); + try (InputStream res = rm.openRawResource(res_id)) { + Log.d("db", "Applying revision " + String.valueOf(rev_no)); + InputStreamReader isr = new InputStreamReader(res); + BufferedReader reader = new BufferedReader(isr); + + String line; + while ((line = reader.readLine()) != null) { + db.execSQL(line); + } + + db.setTransactionSuccessful(); + } + catch (IOException e) { + Log.e("db", String.format("Error opening raw resource for revision %d", rev_no)); + e.printStackTrace(); + } + finally { + db.endTransaction(); } } } -- 2.39.2