diff --git a/app/build.gradle b/app/build.gradle index 6e2850a..0481495 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,7 @@ apply plugin: "com.android.application" apply plugin: "kotlin-android" apply plugin: "kotlin-android-extensions" +apply plugin: "kotlin-kapt" apply plugin: "shot" android { @@ -40,6 +41,9 @@ dependencies { implementation "androidx.constraintlayout:constraintlayout:2.0.0-alpha3" implementation "androidx.recyclerview:recyclerview:1.0.0" implementation "androidx.lifecycle:lifecycle-runtime:2.0.0" + implementation "androidx.room:room-runtime:2.1.0-alpha04" + kapt "androidx.room:room-compiler:2.1.0-alpha04" + implementation "androidx.room:room-coroutines:2.1.0-alpha04" /* Coroutines */ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.0" @@ -71,6 +75,7 @@ dependencies { } androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.1.0" + testImplementation "androidx.room:room-testing:2.1.0-alpha04" } shot { diff --git a/app/src/main/java/com/karumi/jetpack/superheroes/SuperHeroesApplication.kt b/app/src/main/java/com/karumi/jetpack/superheroes/SuperHeroesApplication.kt index b21bd36..4bc942d 100644 --- a/app/src/main/java/com/karumi/jetpack/superheroes/SuperHeroesApplication.kt +++ b/app/src/main/java/com/karumi/jetpack/superheroes/SuperHeroesApplication.kt @@ -2,9 +2,12 @@ package com.karumi.jetpack.superheroes import android.app.Application import android.content.Context +import androidx.room.Room +import com.karumi.jetpack.superheroes.common.SuperHeroesDatabase import com.karumi.jetpack.superheroes.data.repository.LocalSuperHeroDataSource import com.karumi.jetpack.superheroes.data.repository.RemoteSuperHeroDataSource import com.karumi.jetpack.superheroes.data.repository.SuperHeroRepository +import com.karumi.jetpack.superheroes.data.repository.room.SuperHeroDao import org.kodein.di.Kodein import org.kodein.di.KodeinAware import org.kodein.di.android.androidModule @@ -29,11 +32,23 @@ class SuperHeroesApplication : Application(), KodeinAware { private fun appDependencies(): Kodein.Module { return Kodein.Module("Application dependencies", allowSilentOverride = true) { + bind() with singleton { + Room.databaseBuilder( + this@SuperHeroesApplication, + SuperHeroesDatabase::class.java, + "superheroes-db" + ).fallbackToDestructiveMigration() + .build() + } + bind() with provider { + val database: SuperHeroesDatabase = instance() + database.superHeroesDao() + } bind() with provider { SuperHeroRepository(instance(), instance()) } bind() with singleton { - LocalSuperHeroDataSource() + LocalSuperHeroDataSource(instance()) } bind() with provider { RemoteSuperHeroDataSource() diff --git a/app/src/main/java/com/karumi/jetpack/superheroes/common/SuperHeroesDatabase.kt b/app/src/main/java/com/karumi/jetpack/superheroes/common/SuperHeroesDatabase.kt new file mode 100644 index 0000000..bb596dc --- /dev/null +++ b/app/src/main/java/com/karumi/jetpack/superheroes/common/SuperHeroesDatabase.kt @@ -0,0 +1,11 @@ +package com.karumi.jetpack.superheroes.common + +import androidx.room.Database +import androidx.room.RoomDatabase +import com.karumi.jetpack.superheroes.data.repository.room.SuperHeroDao +import com.karumi.jetpack.superheroes.data.repository.room.SuperHeroEntity + +@Database(entities = [SuperHeroEntity::class], version = 1) +abstract class SuperHeroesDatabase : RoomDatabase() { + abstract fun superHeroesDao(): SuperHeroDao +} \ No newline at end of file diff --git a/app/src/main/java/com/karumi/jetpack/superheroes/data/repository/LocalSuperHeroDataSource.kt b/app/src/main/java/com/karumi/jetpack/superheroes/data/repository/LocalSuperHeroDataSource.kt index 7852572..a52bc8c 100644 --- a/app/src/main/java/com/karumi/jetpack/superheroes/data/repository/LocalSuperHeroDataSource.kt +++ b/app/src/main/java/com/karumi/jetpack/superheroes/data/repository/LocalSuperHeroDataSource.kt @@ -1,38 +1,32 @@ package com.karumi.jetpack.superheroes.data.repository +import com.karumi.jetpack.superheroes.data.repository.room.SuperHeroDao +import com.karumi.jetpack.superheroes.data.repository.room.SuperHeroEntity import com.karumi.jetpack.superheroes.domain.model.SuperHero -import kotlinx.coroutines.delay -class LocalSuperHeroDataSource { - companion object { - private const val BIT_TIME = 250L - } - - private val superHeroes: MutableMap = mutableMapOf() +class LocalSuperHeroDataSource( + private val dao: SuperHeroDao +) { + suspend fun getAllSuperHeroes(): List = + dao.getAll() + .map { it.toSuperHero() } - suspend fun getAllSuperHeroes(): List { - waitABit() - return superHeroes.values.toList() - } - - suspend fun get(id: String): SuperHero? { - waitABit() - return superHeroes[id] - } + suspend fun get(id: String): SuperHero? = + dao.getById(id)?.toSuperHero() suspend fun saveAll(all: List) { - waitABit() - superHeroes.clear() - superHeroes.putAll(all.associateBy { it.id }) + dao.deleteAll() + dao.insertAll(all.map { it.toEntity() }) } suspend fun save(superHero: SuperHero): SuperHero { - waitABit() - superHeroes[superHero.id] = superHero + dao.insertAll(listOf(superHero.toEntity())) return superHero } - private suspend fun waitABit() { - delay(BIT_TIME) - } + private fun SuperHeroEntity.toSuperHero(): SuperHero = + SuperHero(id, name, photo, isAvenger, description) + + private fun SuperHero.toEntity(): SuperHeroEntity = + SuperHeroEntity(id, name, photo, isAvenger, description) } \ No newline at end of file diff --git a/app/src/main/java/com/karumi/jetpack/superheroes/data/repository/room/SuperHeroDao.kt b/app/src/main/java/com/karumi/jetpack/superheroes/data/repository/room/SuperHeroDao.kt new file mode 100644 index 0000000..b1b3f35 --- /dev/null +++ b/app/src/main/java/com/karumi/jetpack/superheroes/data/repository/room/SuperHeroDao.kt @@ -0,0 +1,21 @@ +package com.karumi.jetpack.superheroes.data.repository.room + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query + +@Dao +interface SuperHeroDao { + @Query("SELECT * FROM superheroes") + suspend fun getAll(): List + + @Query("SELECT * FROM superheroes WHERE id = :id") + suspend fun getById(id: String): SuperHeroEntity? + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertAll(superHeroes: List) + + @Query("DELETE FROM superheroes") + suspend fun deleteAll() +} \ No newline at end of file diff --git a/app/src/main/java/com/karumi/jetpack/superheroes/data/repository/room/SuperHeroEntity.kt b/app/src/main/java/com/karumi/jetpack/superheroes/data/repository/room/SuperHeroEntity.kt new file mode 100644 index 0000000..2d098e2 --- /dev/null +++ b/app/src/main/java/com/karumi/jetpack/superheroes/data/repository/room/SuperHeroEntity.kt @@ -0,0 +1,13 @@ +package com.karumi.jetpack.superheroes.data.repository.room + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "superheroes") +data class SuperHeroEntity( + @PrimaryKey val id: String, + val name: String, + val photo: String?, + val isAvenger: Boolean, + val description: String +) \ No newline at end of file