1

In my Android app I have a

  1. SQLiteHelper class that extends SQLIteOpenHelper, and takes care of things like table-creation and upgrades.

  2. SQLiteDatasource class that performs CRUD operations on the SQLiteHelper object.

I want to pre-load one of the tables with certain items so there is something present when the user first uses the app. These items may change so I want to make them modular.

Right now I am doing it this way:

public class MyDefaults {
    public static final ArrayList<HashMap<String, String>> MY_DEFAULTS;

    static {
        MY_DEFAULTS = new ArrayList<HashMap<String, String>>();
        HashMap<String, String> map = new HashMap<String, String>();

        //All the values below you change to whatever defaults you want
        map.clear();
        map.put(SQLiteHelper.KEY_1, "Value 1A");
        map.put(SQLiteHelper.KEY_2, "Value 2A");
        map.put(SQLiteHelper.KEY_3, "Value 3A");
        MY_DEFAULTS.add(new HashMap<String, String>(map));

        map.clear();
        map.put(SQLiteHelper.KEY_1, "Value 1B");
        map.put(SQLiteHelper.KEY_2, "Value 2B");
        map.put(SQLiteHelper.KEY_3, "Value 3B");
        MY_DEFAULTS.add(new HashMap<String, String>(map));

        map.clear();
        map.put(SQLiteHelper.KEY_1, "Value 1C");
        map.put(SQLiteHelper.KEY_2, "Value 2C");
        map.put(SQLiteHelper.KEY_3, "Value 3C");
        MY_DEFAULTS.add(new HashMap<String, String>(map));

        //and so on
    }

}

And then in my SQLiteDatasource class I have a method that performs the insert of these default values:

public void preloadDefaults() {
    mDatabase.beginTransaction();

    try {
        for (HashMap<String, String> map : MyDefaults.MY_DEFAULTS) {
            ContentValues values = new ContentValues();
            values.put(SQLiteHelper.KEY_1, map.get(SQLiteHelper.KEY_1));
            values.put(SQLiteHelper.KEY_2, map.get(SQLiteHelper.KEY_2));
            values.put(SQLiteHelper.KEY_3, map.get(SQLiteHelper.KEY_3));
            mDatabase.insert(SQLiteHelper.SOME_TABLE, null, values);
        }
    }
    finally {
        mDatabase.endTransaction();
    }
}

Is my way of doing this considered bad practice? Is there a better way to define the "defaults" that get inserted into a table after it gets created? Possibly through XML instead of a static class?

Note: I can't just copy an external DB because I'm actually inserting these fields with some other values created at runtime (the code above is a simplification of what my real code is).

AJJ
  • 2,004
  • 4
  • 28
  • 42
  • 1
    I'd probably go with a CSV file. Make the input look as much like the storage as possible. – Corey Ogburn Mar 29 '16 at 15:07
  • @CoreyOgburn That's a really interesting idea. However I don't see any CSV readers in the autocomplete. Is there any particular method you'd recommend? – AJJ Mar 29 '16 at 15:09
  • 1
    I also started looking because I might do this in one of my projects. Anybody who has recommendations always mentions [OpenCSV](http://opencsv.sourceforge.net/) but I have no experience with it (yet). – Corey Ogburn Mar 29 '16 at 15:11
  • I used OpenCSV in one of my project, and I had no problem. – GVillani82 Mar 29 '16 at 15:15
  • I am new to this Android / open-source stuff -- how would I incorporate OpenCSV into my project? – AJJ Mar 29 '16 at 15:16
  • That's a whole different question, seemingly answered here: http://stackoverflow.com/questions/16588064/how-do-i-add-a-library-project-to-the-android-studio – Corey Ogburn Mar 29 '16 at 15:17
  • Possible duplicate of [How to ship an Android application with a database?](http://stackoverflow.com/questions/513084/how-to-ship-an-android-application-with-a-database) – bendaf Mar 29 '16 at 15:17
  • You can add a csv file in raw folder, and then access it using a CSVReader. And then you can do everything you whant with those data. – GVillani82 Mar 29 '16 at 15:18
  • @Joseph82 Would I need to add CSVReader to my project the same way I'd add OpenCSV? – AJJ Mar 29 '16 at 15:20
  • @bendaf Maybe it technically is, but the accepted answer has a comment condemning that solution. Your own answer is more direct. – Corey Ogburn Mar 29 '16 at 15:20
  • @bendaf For reasons I didn't get into, I can't just copy an external DB because I'm actually inserting these fields with some other values created at runtime, so right now the CSV approach seems more appropriate – AJJ Mar 29 '16 at 15:20
  • No @ArukaJ CSVReader is a class, provided from OpenCSV, that you can use for reading the csv file. – GVillani82 Mar 29 '16 at 15:21
  • Is OpenCSV not in Maven where I can just add a compile line to the dependencies in the gradle? – AJJ Mar 29 '16 at 15:39
  • Maybe it is 'net.sf.opencsv:opencsv:2.3' according to http://mvnrepository.com/artifact/net.sf.opencsv/opencsv/2.3 ? – AJJ Mar 29 '16 at 15:41
  • I guess that worked, I seem to have the CSV functions now – AJJ Mar 29 '16 at 15:42
  • If you want to know how to parse csv file please look at this link: http://www.theappguruz.com/blog/parse-csv-file-in-android-example-sample-code – Chintan Desai Mar 29 '16 at 15:44
  • @ArukaJ if you know your data you do not need to include that but my advise is to keep the headers. – Chintan Desai Mar 29 '16 at 16:07

2 Answers2

1

As it is in this answer also The SQLiteAssetHelper library makes this task really simple.

It's easy to add as a gradle dependency (but a Jar is also available for Ant/Eclipse), and together with the documentation it can be found at:
https://github.com/jgilfelt/android-sqlite-asset-helper

As explained in documentation:

  1. Add the dependency to your module's gradle build file:

    dependencies {
        compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+'
    }
    
  2. Copy the database into the assets directory, in a subdirectory called assets/databases. For instance:
    assets/databases/my_database.db

    (Optionally, you may compress the database in a zip file such as assets/databases/my_database.zip. This isn't needed, since the APK is compressed as a whole already.)

  3. Create a class, for example:

    public class MyDatabase extends SQLiteAssetHelper {
    
        private static final String DATABASE_NAME = "my_database.db";
        private static final int DATABASE_VERSION = 1;
    
        public MyDatabase(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }
    }
    
Community
  • 1
  • 1
bendaf
  • 2,981
  • 5
  • 27
  • 62
0

You can memorize your data, with Serialize Objects. Read here:

How do I serialize an object and save it to a file in Android?

Community
  • 1
  • 1
Rubber
  • 66
  • 6
  • I'm not sure this really addresses my core problem -- and isn't Parcelable much faster than Serializable in Android? – AJJ Mar 29 '16 at 15:56
  • Yep, but the Parceleable Objects, have a significant amount of boilerplate code and it makes the classes harder to read and maintain – Rubber Mar 30 '16 at 08:44