W poprzednim poście wspominałem o różnych możliwych drogach początkowej inicjalizacji bazy danych dla aplikacji pisanych na androida, w przypadku poprzedniej aplikacji zdecydowałem się na najprostsze (jednocześnie brzydkie) rozwiązanie - kod sql jako pola z modyfikatorami private static final. Wówczas podejście to było akceptowalne ze względu na małą ilość danych, którymi musiałem zasilić bazę.

W przypadku kolejnej aplikacji (właściwie widgetu przypominającego o imieninach) danych, którymi trzeba zasilić bazę jest dużo więcej. Zdecydowałem się więc na inne podejście. Dane, które zasilą bazę danych przechowywane będą w pliku csv dołączonym do aplikacji (plik znajdował będzie się w archiwum apk). Standarowa struktura projektu umożliwa przechowywanie takich plików w dwóch miejscach:

  • res/raw,
  • assets.

W moim przypadku, zdecydowałem się na umieszczenie pliku csv w katalogu assets/ ponieważ zależy mi na dostępie do pliku na podstawie nazwy pliku a nie jego identyfikatora generowanego automatycznie (w przypadku plików w res/raw mamy do nich dostęp za pośrednictwem zestawu metod Resources.openRawResource() gdzie jako argument przekazujemy idenyfikator źródła z klasy R).

Poniżej prezentuję fragmenty kodu odpowiedzialne za utworzenie nowej bazy danych, zasilenie jej danymi z pliku oraz parsowanie pliku csv.

public class SaintsDayDbHelper extends SQLiteOpenHelper {

    // unfortunatelly context in parent isn't accessible ):
    private Context context;
    // ...

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_DB_STMT);
        new DbSeeder(context.getAssets(), db).seedDb();
    }
    // ...
}

Poniżej kod klasy DbSeeder odpowiedzialnej za zasilenie nowotworzonej bazy danymi. Jak widać klasa ta używa klasy CsvParser do parsowania pliku z danymi. W ten sposób utworzone rekordy są następnie wrzucane do bazy.

public class DbSeeder {

    private static final String RAW_DATA_FILE_PATH = "pl_saints_days.csv";

    private SQLiteDatabase db;
    private AssetManager assetsManager;
    // ...

    public void seedDb() {
        CsvParser parser = new CsvParser(assetsManager, RAW_DATA_FILE_PATH);
        try {
            db.beginTransaction();
            CsvParser.Record record = null;
            while((record = parser.readRecord()) != null) {
                insertRows(record);
            }
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
            parser.close();
        }
    }
    // ...
}

Poniżej kod klasy odpowiedzialnej za parsowanie pliku csv. Właśnie w tym miejscu uzyskujemy dostęp do “surowego” pliku z katalogu assets/, przy pomocy AssetsManager.open().

class CsvParser {

    private BufferedReader reader;
    // ...

    public CsvParser(AssetManager manager, String filePath) {
        try {
            InputStream inputStream = manager.open(filePath);
            reader = new BufferedReader(new InputStreamReader(inputStream));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    // ...
}

Wyżej prezentowane są wyłącznie fragmenty kodu, po całość odsyłam na moje konto na githubie.

Podobne posty