Android Room Tutorial: Simplifying How You Work with App Data

Az információ valószínűleg a legfontosabb erőforrás, amelyben a felhasználók megbíznak az alkalmazásokkal kapcsolatban. Az alkalmazásfejlesztők számára ezek az információk elárulják, hogy ki a felhasználó, ami képessé tesz minket arra, hogy jó felhasználói élményt (UX) nyújtsunk. Emellett azáltal, hogy üzleti szabályokat alkalmazunk ezekre az információkra, meghatározzuk azt a viselkedést, amellyel az alkalmazásnak rendelkeznie kell. Ezek az információk érzékenyek lehetnek, és felfedhetik a felhasználók személyes adatait, ezért nagyon fontos, hogy helyesen kezeljük őket, hogy biztosítsuk integritásukat, adatvédelmüket és megfelelő tárolásukat. Ebben az Android Room bemutatóban megmutatjuk, hogyan dolgozhatsz könnyebben ezekkel az adatokkal, miközben biztosítod az integritását és biztonságát, mindezt a Room használatával. A Room az Android Architecture Components része.

Szüksége van a Room-ra?

Amikor az információk tartós tárolásáról beszélünk Androidon, a legfontosabb és “egyszerű” lehetőség a sima SQLite használata. Azonban egy jó adatbázis implementáció SQLite használatával rengeteg olyan kód generálásával jár, amely nem nyújt valódi értéket. A következő architektúra gyakran nem olyan tiszta és világos, mint amilyen lehetne.

Az objektum-relációs leképezést, vagyis az ORM-et is használhatná, de akkor is kézzel kell definiálnia és létrehoznia az adatbázist, az SQLiteOpenHelper alosztályozásával és a szerződéses osztályok létrehozásával.

A kérdés tehát az, hogy van-e mód arra, hogy mindezt a folyamatot leegyszerűsítsük? A válasz: Igen, a szoba a megoldás.

A Room közelebbi megnézése és működése

A Room az Android Architectural Components egyik legfontosabb eszköze. A 2016-os Google I/O-n jelent meg, és egy hatékony eszköz az Android-alkalmazások információinak tárolására és manipulálására. Nagyon egyszerű módot biztosít az adatokkal való munkához, és mindig gondoskodik azok biztonságáról és integritásáról.

A Room nem egy ORM, hanem egy teljes könyvtár, amely lehetővé teszi számunkra az SQLite adatbázisok könnyebb létrehozását és manipulálását. Annotációk segítségével definiálhatjuk adatbázisainkat, tábláinkat és műveleteinket. A Room automatikusan lefordítja ezeket az annotációkat SQLite utasításokká/kérdésekké, hogy a megfelelő műveleteket elvégezze az adatbázis-motorban.

A Room három fő összetevője a következő:

– Entity: Egy táblát képvisel a Room adatbázisban. A @Entity-vel kell annotálni.

– DAO: Egy interfész, amely az adatbázis eléréséhez szükséges metódusokat tartalmazza. A @Dao.

– Adatbázissal kell annotálni: Az adatbázist reprezentálja. Ez egy objektum, amely kapcsolatot tart az SQLite adatbázishoz, és minden művelet ezen keresztül kerül végrehajtásra. A @Datbázis megjegyzésekkel van ellátva.

A terem architektúra így néz ki:

Android Room architektúra

Túl sok beszéd – nézzünk egy példát

Merüljünk bele ebbe az Android Room bemutatóba. Képzeljük el, hogy egy alkalmazást kell létrehoznunk az edzésprogramunk tárolására. Négy entitásunk lesz az adatbázisunkban, ahogy azt az alábbiakban bemutatjuk. Az összes mintakód Kotlin használatával íródott (ha nem ismeri a Kotlint, vagy többet szeretne tanulni, meghívom, hogy olvassa el a róla szóló cikkemet).

Az első dolog, amit tennünk kell, hogy frissítjük a gradle fájlunkat. Így kell kinéznie:

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'}

Lássuk és elemezzük a három fő Room komponens mindegyikét: Entitások, DAO-k és adatbázis.

Entitások

Példánkban négy entitást fogunk használni: Nem, Gyakorlat, Rutin és Gyakornok.

Gender.kt

Reprezentálja a gyakornok nemét

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

Megfigyelhető dolgok:

– Minden olyan osztályt, amely az adatbázis egy entitását reprezentálja, @Entity-vel kell annotálni

– Az @PrimaryKey(autoGenerate = true) annotációval jelezzük, hogy az id az entitás elsődleges kulcsa és az adatbázis motorjának automatikusan kell generálnia.

Exercise.kt

Egy rutin részét képező gyakorlatot reprezentál.

@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)

Megfigyelhető dolgok:

– Alapértelmezés szerint a Room a mezőneveket használja az adatbázis oszlopneveként. Ha azt szeretnénk, hogy egy oszlopnak más neve legyen, adjuk hozzá a mezőhöz a @ColumnInfo annotációt.

Routine.kt

– Alapvetően gyakorlatok tárolója, amelyek együttesen egy gyakorlatrutint alkotnak.

@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)

Mit vegyünk észre:

– Ha egy osztály @Entity-vel van annotálva, akkor a táblázat neve az osztály neve lesz. Ha más nevet szeretnénk használni, akkor a @Entity annotációval együtt hozzá kell adnunk a tableName tulajdonságot is.

– A @TypeConverters annotációt akkor kell használni, ha olyan tulajdonságot deklarálunk, amelynek a típusa egy egyéni osztály, egy lista, egy dátumtípus vagy bármilyen más típus, amelyet a Room és az SQL nem tudja, hogyan kell szerializálni. Ebben az esetben az annotációt az osztály mezőjének szintjén használjuk, ami által csak az adott mező fogja tudni használni. Attól függően, hogy az annotációt hol helyezzük el, másképp fog viselkedni, ahogy azt itt elmagyarázzuk.

Trainee.kt

Ez képviseli a rutin tulajdonosát.

@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

Az adatelérési objektumok (DAOs) a Room implementálásakor az adataink elérésére szolgálnak. Minden DAO-nak tartalmaznia kell egy sor metódust az adatok manipulálásához (insert, update, delete, vagy get).

A DAO-t megvalósíthatjuk interfészként vagy absztrakt osztályként. A mi esetünkben interfészt használunk. Mivel az összes DAO alapvetően azonos, ezért csak egyet mutatunk be.

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}

Meg kell jegyeznünk néhány dolgot:

– Minden DAO-t @Dao-val kell annotálni.

– Egy @Insert, @Update vagy @Delete annotált függvénynek paraméterként a kívánt osztály egy példányát kell fogadnia, amely a beszúrni, frissíteni vagy törölni kívánt objektumot jelenti.

– A beszúrási vagy frissítési műveletek esetében az onConflict tulajdonsággal jelezhetjük, hogy mit tegyünk, ha a művelet végrehajtása során konfliktus lép fel. A rendelkezésre álló stratégiák a következők: REPLACE, ABORT, FAIL, IGNORE és ROLLBACK.

– Ha egy vagy több entitásból konkrét információt szeretnénk kinyerni, akkor egy függvényt @Query-vel annotálhatunk, és paraméterként megadhatunk egy SQL-szkriptet.

Database

Reprezentálja az adatbázist. Tartja a kapcsolatot a tényleges SQLite adatbázissal.

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 } }}

Az itt megjegyzendő dolgok:

– Ez egy absztrakt osztály, amelynek a RoomDatabase-t kell bővítenie.

– A @Database-vel kell annotálni, és megkapja az entitások listáját az összes olyan osztállyal, amely az adatbázist alkotja (ezeket az osztályokat @Entity-vel kell annotálni). Meg kell adnunk az adatbázis verzióját is.

– Minden egyes, a @Database annotációban szereplő entitáshoz deklarálnunk kell egy absztrakt függvényt. Ennek a függvénynek vissza kell adnia a megfelelő DAO-t (egy @Dao annotációval annotált osztály).

– Végül deklarálnunk kell egy társobjektumot, hogy statikus hozzáférést kapjunk a getAppDataBase metódushoz, amely az adatbázis egy singleton példányát adja nekünk.

Type Converters

Type Converters-t akkor használjuk, ha olyan tulajdonságot deklarálunk, amelyet a Room és az SQL nem tudja, hogyan kell szerializálni. Lássunk egy példát arra, hogyan szerializálhatunk egy ‘dátum’ adattípust.

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 }}

A Room adatbázis használata

Most nézzünk egy nagyon egyszerű példát arra, hogyan használhatjuk az imént létrehozott Room adatbázist:

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 csinálunk?

– Az adatbázis és a GenderDao példányának megszerzése.

– Két Gender példány létrehozása: Férfi és Nő.

– A létrehozott két példány beillesztése az adatbázisba.

– Az adatbázis lekérdezése, hogy megkapjuk az adatbázisban tárolt összes nemet.

– Az adatbázisból kapott összes nem nevének összevonása, és a TextView szövegének beállítása ezzel az értékkel.

Room to Do More with Less

A szoba az Android Architectural Components egyik fontos eleme. Nagyon robusztus keretet biztosít számunkra a munkához és a tartós információkhoz, mindig garantálva az adatok biztonságát és integritását. Emellett könnyű kezelhetőséget biztosít a fejlesztők számára, így olvasható és magától értetődő kódot írhatnak. Ha kevesebb kóddal többet akarsz elérni, és a felhasználói adatok biztonságát is biztosítani akarod, akkor a Roomot kell használnod az alkalmazásodban a perzisztencia rétegként.

És ennyi! Ez majdnem minden, amit tudnod kell ahhoz, hogy létrehozz és használj egy adatbázist Androidon a Room segítségével. A projekt teljes kódját itt találod. Köszönjük, hogy elolvastad ezt az Android Room bemutatót!

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.