Android Room Tutorial: Simplifying How You Work with App Data

Tieto on luultavasti tärkein resurssi, johon käyttäjät luottavat sovelluksissa. Sovelluskehittäjille nämä tiedot kertovat, kuka käyttäjä on, mikä antaa meille valtuudet tarjota hyvän käyttäjäkokemuksen (UX). Soveltamalla liiketoimintasääntöjä näihin tietoihin määrittelemme myös käyttäytymisen, joka sovelluksella pitäisi olla. Nämä tiedot voivat olla järkeviä ja paljastaa käyttäjien yksityisiä tietoja, joten on erittäin tärkeää, että käsittelemme niitä oikein varmistaaksemme niiden eheyden, yksityisyyden ja asianmukaisen tallennuksen. Tässä Android Room -oppaassa näytämme, miten voit työskennellä näiden tietojen kanssa helpommin ja samalla varmistaa niiden eheyden ja turvallisuuden, ja kaikki tämä käyttämällä Roomia. Room on osa Android-arkkitehtuurin komponentteja.

Tarvitsetko Roomia?

Kun puhumme tietojen tallentamisesta pysyvällä tavalla Androidissa, tärkein ja ”helpoin” vaihtoehto on käyttää tavallista SQLiteä. Hyvän tietokantatoteutuksen saaminen SQLiteä käyttäen merkitsee kuitenkin paljon koodin tuottamista, joka ei tuota todellista arvoa. Tästä seuraava arkkitehtuuri ei useinkaan ole niin puhdas tai selkeä kuin se voisi olla.

Voisit myös käyttää olio-relaatiokartoitusta eli ORM:ää, mutta sinun on silti määriteltävä ja luotava tietokanta manuaalisesti, aliluokitettava SQLiteOpenHelper ja luotava sopimusluokat.

Kysymys kuuluu siis: Voiko tätä kaikkea prosessia yksinkertaistaa mitenkään? Vastaus on: Kyllä, huone on ratkaisu.

Roomin tarkempi tarkastelu ja sen toiminta

Room on yksi Android-arkkitehtuurikomponenttien tärkeimmistä työkaluista. Se julkaistiin Google I/O 2016 -tapahtumassa, ja se on tehokas työkalu tietojen tallentamiseen ja käsittelyyn Android-sovelluksissa. Se tarjoaa erittäin helpon tavan työskennellä tietojen kanssa ja varmistaa aina niiden turvallisuuden ja eheyden.

Room ei ole ORM, vaan se on kokonainen kirjasto, jonka avulla voimme luoda ja käsitellä SQLite-tietokantoja helpommin. Annotaatioiden avulla voimme määritellä tietokantamme, taulukot ja operaatiot. Room kääntää nämä annotaatiot automaattisesti SQLite-ohjeiksi/kyselyiksi vastaavien operaatioiden suorittamiseksi tietokantamoottoriin.

Roomin kolme pääkomponenttia ovat:

– Entiteetti: Edustaa taulukkoa Room-tietokannassa. Se tulee annotoida @Entityllä.

– DAO: Rajapinta, joka sisältää metodit tietokannan käyttämiseen. Se annotoidaan merkinnällä @Dao.

– Database: Edustaa tietokantaa. Se on olio, jolla on yhteys SQLite-tietokantaan, ja kaikki operaatiot suoritetaan sen kautta. Se on annotoitu merkinnällä @Database.

Roomin arkkitehtuuri näyttää tältä:

Android Roomin arkkitehtuuri

Too much talk-Let’s look at an example

Sukelletaan tähän Android Roomin opetusohjelmaan. Kuvittele, että meidän on luotava sovellus, joka tallentaa kuntosalirutiinisi. Tietokannassamme tulee olemaan neljä oliota, kuten näytämme alla. Kaikki esimerkkikoodi on kirjoitettu käyttäen Kotlinia (jos et tunne Kotlinia tai haluat oppia lisää, kutsun sinut lukemaan artikkelini siitä).

Ensin meidän on päivitettävä gradle-tiedostomme. Sen pitäisi näyttää tältä:

apply plugin: 'com.android.application'apply plugin: 'kotlin-android'apply plugin: 'kotlin-android-extensions'apply plugin: 'kotlin-kapt'android { //.. Omitted since it is not relevant for the example}dependencies { //... some dependencies were omitted due to they are not relevant for the example def room_version = "2.2.0-rc01" implementation "androidx.room:room-runtime:$room_version" kapt "androidx.room:room-compiler:$room_version" compile 'com.google.code.gson:gson:2.2.4' implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' implementation 'io.reactivex.rxjava2:rxjava:2.1.17'}

Katsotaan ja analysoidaan jokainen kolmesta suuresta Room-komponentista: Entiteetit, DAO:t ja tietokanta.

Entiteetit

Esimerkissämme käytämme neljää entiteettiä: Gender, Exercise, Routine ja Trainee.

Gender.kt

Kuvastaa harjoittelijan sukupuolta

@Entitydata class Gender( @PrimaryKey(autoGenerate = true) val id: Int? = null, val name: String)

Huomioitavaa:

– Kaikki luokat, jotka edustavat tietokannan oliota, on annotoitava merkinnällä @Entity

– Annotaatiolla @PrimaryKey(autoGenerate=tulee=todennäköinen) osoitamme, että id on olion primääriavain ja että tietokantamoottorin pitäisi generoida se automaattisesti.

Exercise.kt

Kuvastaa harjoitusta, joka on osa rutiinia.

@Entitydata class Exercise( @PrimaryKey(autoGenerate = true) val exerciseId: Int, val name: String, val repetitions:Int, @ColumnInfo(name = "machine_name") val machineName: String, val liftedWeight: Int)

Huomioitavaa:

– Oletuksena Room käyttää kenttien nimiä tietokannan sarakkeiden niminä. Jos haluat sarakkeelle eri nimen, lisää kenttään @ColumnInfo -annotaatio.

Rutiini.kt

Periaatteessa säiliö harjoituksista, jotka yhdessä muodostavat harjoitusrutiinin.

@Entity(tableName = "traineeRoutine")data class Routine( @PrimaryKey(autoGenerate = true) val routineId: Int, @ColumnInfo(name = "due_day") val dueDay: Date, @TypeConverters(ListConverter::class) val exercises: List)

Huomioitavaa:

– Kun luokka on annotoitu @Entity-annotaatiolla, taulukon nimi on luokan nimi. Jos haluamme käyttää eri nimeä, meidän on lisättävä tableName-ominaisuus yhdessä @Entity-annotaation kanssa.

– @TypeConverters-annotaatiota on käytettävä, kun ilmoitamme ominaisuuden, jonka tyyppi on mukautettu luokka, lista, päivämäärätyyppi tai jokin muu tyyppi, jota Room ja SQL eivät osaa serialisoida. Tässä tapauksessa käytämme annotaatiota luokan kentän tasolla, jolloin vain kyseinen kenttä voi käyttää sitä. Riippuen siitä, mihin annotaatio sijoitetaan, se käyttäytyy eri tavalla, kuten tässä selitetään.

Trainee.kt

Se edustaa rutiinin omistajaa.

@Entity(indices = , foreignKeys = , childColumns = )])data class Trainee( @PrimaryKey(autoGenerate = true) val id: Int, val name: String, val age: Int, val gender: Int?, @Embedded val routine: Routine)

DAOs

Data Access Objects (DAOs) -objekteja (data access objects) käytetään tietojemme käyttämiseen, kun toteutamme Room. Jokaisen DAO:n on sisällettävä joukko metodeja, joilla tietoja voidaan käsitellä (lisätä, päivittää, poistaa tai hakea).

DAO voidaan toteuttaa rajapintana tai abstraktina luokkana. Meidän tapauksessamme käytämme rajapintaa. Koska kaikki DAO:t ovat periaatteessa identtisiä, näytämme vain yhden.

GenderDao.kt@Daointerface GenderDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insertGender(gender: Gender) @Update fun updateGender(gender: Gender) @Delete fun deleteGender(gender: Gender) @Query("SELECT * FROM Gender WHERE name == :name") fun getGenderByName(name: String): List @Query("SELECT * FROM Gender") fun getGenders(): List}

Huomioitavaa on muutama asia:

– Kaikki DAO:t on annotoitava @Dao:lla.

– Funktio, joka on annotoitu @Insert-, @Update- tai @Delete-merkinnällä, joutuu vastaanottamaan parametrina halutun luokan instanssin, joka edustaa objektia, jonka haluamme lisätä, päivittää tai vastaavasti poistaa.

– Insert- tai update-operaatioiden tapauksessa voimme käyttää onConflict-ominaisuutta ilmaisemaan, mitä tehdään, kun operaatiota suoritettaessa syntyy konflikti. Käytettävissä olevat strategiat ovat: REPLACE, ABORT, FAIL, IGNORE ja ROLLBACK.

– Jos haluamme saada tiettyä tietoa yhdestä tai useammasta oliosta, voimme merkitä funktioon @Query-merkinnän ja antaa parametrina SQL-skriptin.

Database

Kuvastaa tietokantaa. Se pitää sisällään yhteyden varsinaiseen SQLite-tietokantaan.

AppDatabase.kt@Database(entities = , version = 1)@TypeConverters(DateTypeConverter::class)abstract class AppDatabase : RoomDatabase() { abstract fun exerciseDao(): ExerciseDao abstract fun genderDao(): GenderDao abstract fun routineDao(): RoutineDao abstract fun traineeDao(): TraineeDao companion object { var INSTANCE: AppDatabase? = null fun getAppDataBase(context: Context): AppDatabase? { if (INSTANCE == null){ synchronized(AppDatabase::class){ INSTANCE = Room.databaseBuilder(context.applicationContext, AppDatabase::class.java, "myDB").build() } } return INSTANCE } fun destroyDataBase(){ INSTANCE = null } }}

Huomioitavaa tässä:

– Tämä on abstrakti luokka, jonka on laajennettava RoomDatabase-luokkaa.

– Se on annotoitava @Database-merkinnällä, ja se vastaanottaa luettelon olioista, joissa on kaikki tietokannan muodostavat luokat (kaikki nämä luokat on annotoitava @Entity-merkinnällä). Meidän on myös annettava tietokannan versio.

– Meidän on ilmoitettava abstrakti funktio jokaiselle @Database-annotaatioon sisältyvälle oliolle. Tämän funktion on palautettava vastaava DAO (luokka, joka on annotoitu @Dao:lla).

– Lopuksi deklarisoimme companion-olion, jolla saamme staattisen pääsyn metodiin getAppDataBase, joka antaa meille singleton-instanssin tietokannasta.

Tyypinmuunnin

Tyypinmuunninta käytetään silloin, kun deklarisoimme ominaisuuden, jota Room ja SQL eivät osaa sarjata. Katsotaanpa esimerkki siitä, miten sarjallistetaan ’date’-tietotyyppi.

DateTypeConverter.ktclass DateTypeConverter { @TypeConverter fun fromTimestamp(value: Long?): Date? { return if (value == null) null else Date(value) } @TypeConverter fun dateToTimestamp(date: Date?): Long? { return date?.time }}

Room-tietokannan käyttäminen

Katsotaanpa nyt hyvin yksinkertainen esimerkki siitä, miten juuri luomamme Room-tietokantaa käytetään:

MainActivity.ktclass MainActivity : AppCompatActivity() { private var db: AppDatabase? = null private var genderDao: GenderDao? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) Observable.fromCallable({ db = AppDatabase.getAppDataBase(context = this) genderDao = db?.genderDao() var gender1 = Gender(name = "Male") var gender2 = Gender(name = "Female") with(genderDao){ this?.insertGender(gender1) this?.insertGender(gender2) } db?.genderDao()?.getGenders() }).doOnNext({ list -> var finalString = "" list?.map { finalString+= it.name+" - " } tv_message.text = finalString }).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe() }}

Mitä teemme?

– Hankitaan tietokannan instanssi ja GenderDao.

– Luodaan kaksi Gender-instanssia: Mies ja Nainen.

– Kahden luodun instanssin lisääminen tietokantaan.

– Kyselemme tietokannasta saadaksemme kaikki tietokantaan tallennetut sukupuolet.

– Yhdistämme kaikkien tietokannasta saamiemme sukupuolten nimet ja asetamme tekstinäytön tekstin tekstin kyseiseen arvoon.

Tila tehdä enemmän vähemmällä

Tila on yksi Androidin arkkitehtuurin komponenttien tärkeistä tekijöistä. Se antaa meille erittäin vankan kehyksen työskentelyyn ja pysyviin tietoihin, varmistaen aina tietoturvan ja eheyden. Se tarjoaa myös helppokäyttöisyyttä kehittäjille, jotta he voivat kirjoittaa luettavaa ja itsestään selvää koodia. Jos haluat tehdä enemmän vähemmällä koodilla ja myös varmistaa käyttäjätietojen turvallisuuden, sinun pitäisi käyttää Roomia sovelluksesi pysyvyyskerroksena.

Ja siinä se! Tässä on melkein kaikki, mitä sinun tarvitsee tietää luodaksesi ja käyttääksesi tietokantaa Androidissa Roomin avulla. Saat tämän projektin koko koodin täältä. Kiitos, kun luit tämän Android Room -oppaan!

Vastaa

Sähköpostiosoitettasi ei julkaista.