Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #31: Create Room Database & Issue #33: Save Characters from the service to the Database #35

Merged
merged 1 commit into from
Dec 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions buildSrc/src/main/java/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ object Versions {
internal const val fabricTools = "1.31.2"
internal const val materialVersion = "1.0.0"
internal const val cardView = "28.0.0"
internal const val roomVersion = "2.2.3"
}

object GradleDependencies {
Expand Down Expand Up @@ -73,4 +74,6 @@ object LibsDependencies {
const val glide = "com.github.bumptech.glide:glide:${Versions.glide}"
const val glideAnnotation = "com.github.bumptech.glide:compiler:${Versions.glide}"
const val httpLoggingInterceptor = "com.squareup.okhttp3:logging-interceptor:${Versions.httpLoggingInterceptorVersion}"
const val room = "androidx.room:room-runtime:${Versions.roomVersion}"
const val roomCompiler = "androidx.room:room-compiler:${Versions.roomVersion}"
}
11 changes: 11 additions & 0 deletions data/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply from: "$rootDir/detekt.gradle"

def apiPropertiesFile = rootProject.file("api.properties")
Expand All @@ -20,6 +21,12 @@ android {
buildConfigField("String", "MARVEL_PRIVATE_KEY", apiProperties['MARVEL_PRIVATE_KEY'])
buildConfigField("String", "MARVEL_PUBLIC_KEY", apiProperties['MARVEL_PUBLIC_KEY'])
buildConfigField("String", "TIME_STAMP", apiProperties['TIME_STAMP'])

javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.incremental":"true"]
}
}
}

buildTypes {
Expand All @@ -39,13 +46,17 @@ dependencies {
implementation SupportDependencies.appCompat
implementation SupportDependencies.coreKtx

implementation LibsDependencies.room
kapt LibsDependencies.roomCompiler

api LibsDependencies.retrofit2
api LibsDependencies.retrofitGson
api LibsDependencies.httpLoggingInterceptor

testImplementation TestDependencies.junit
testImplementation TestDependencies.robolectric
testImplementation TestDependencies.coroutinesTest

androidTestImplementation TestDependencies.testJunit
androidTestImplementation TestDependencies.espressoCore
}
20 changes: 20 additions & 0 deletions data/src/main/java/com/architect/coders/mu8/data/DataApp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.architect.coders.mu8.data

import android.app.Application
import androidx.room.Room
import com.architect.coders.mu8.data.database.MU8Database

open class DataApp : Application() {

lateinit var database: MU8Database
private set

override fun onCreate() {
super.onCreate()
database = Room.databaseBuilder(
this,
MU8Database::class.java,
"MU8-db"
).build()
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.architect.coders.mu8.data.local.categories
package com.architect.coders.mu8.data.categories

import com.architect.codes.mu8.CHARACTERS
import com.architect.codes.mu8.COMICS
import com.architect.codes.mu8.EVENTS
import com.architect.codes.mu8.utils.CHARACTERS
import com.architect.codes.mu8.utils.COMICS
import com.architect.codes.mu8.utils.EVENTS
import com.architect.codes.mu8.categories.Category

class CategoriesRepository {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.architect.coders.mu8.data.characters

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy.IGNORE
import androidx.room.Query

@Dao
interface CharactersDAO {

@Query("SELECT * FROM CharactersEntity")
fun getAllCharacters(): List<CharactersEntity>

@Query("SELECT COUNT(id) FROM CharactersEntity")
fun charactersCount(): Int

@Insert(onConflict = IGNORE)
fun insertCharacters(characters: List<CharactersEntity>)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.architect.coders.mu8.data.characters

import androidx.room.Entity
import androidx.room.PrimaryKey
import com.architect.coders.mu8.data.response.common.ThumbnailEntity
import com.architect.coders.mu8.data.response.common.UrlsEntity
import com.architect.codes.mu8.utils.EMPTY_STRING

@Entity
data class CharactersEntity(
@PrimaryKey(autoGenerate = false) val id: Long = 0L,
val name: String = EMPTY_STRING,
val description: String = EMPTY_STRING,
val thumbnail: ThumbnailEntity,
val urls: List<UrlsEntity>
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import com.architect.coders.mu8.data.mapper.common.UrlsMapper
import com.architect.coders.mu8.data.utils.replaceHttps
import com.architect.codes.mu8.characters.Character

class CharactersMapper(private val urlsMapper: UrlsMapper) : BaseResponseMapper<CharactersResponse, Character>() {
class CharactersMapper(
private val urlsMapper: UrlsMapper
) : BaseResponseMapper<CharactersEntity, Character>() {

override fun transform(input: CharactersResponse): Character {
override fun transform(input: CharactersEntity): Character {
return Character(
input.id,
input.name,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,40 @@
package com.architect.coders.mu8.data.characters

import com.architect.coders.mu8.data.service.MarvelServiceManager
import com.architect.coders.mu8.data.DataApp
import com.architect.coders.mu8.data.service.MarvelServiceManager.hashcode
import com.architect.coders.mu8.data.service.MarvelServiceManager.service
import com.architect.coders.mu8.data.utils.DEFAULT_OFFSET
import com.architect.coders.mu8.data.utils.LIMIT
import com.architect.coders.mu8.data.utils.MARVEL_PUBLIC_KEY
import com.architect.coders.mu8.data.utils.TIME_STAMP
import com.architect.codes.mu8.characters.Character
import com.architect.codes.mu8.characters.CharactersRepository
import com.architect.codes.mu8.common.Scope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class CharactersRepositoryImpl(
private val mapper: CharactersMapper
) : CharactersRepository, Scope by Scope.Implementation() {
private val mapper: CharactersMapper,
application: DataApp
) : CharactersRepository {

init {
initScope()
}
private val database = application.database

override suspend fun invoke(): List<Character> {
val response = MarvelServiceManager.service.getAllCharacters(TIME_STAMP, MARVEL_PUBLIC_KEY, hashcode)
override suspend fun invoke(): List<Character> = withContext(Dispatchers.IO) {
with(database.getCharactersDao()) {
if (charactersCount() <= 0) {
val response = service.getAllCharacters(
TIME_STAMP,
MARVEL_PUBLIC_KEY,
hashcode,
DEFAULT_OFFSET,
LIMIT
)

val characters = mutableListOf<Character>()
if (response.isSuccessful) {
response.body()?.data?.results?.forEach {
characters.add(mapper.transform(it))
if (response.isSuccessful) {
response.body()?.data?.results?.run { insertCharacters(this) }
}
}
return@withContext getAllCharacters().map { mapper.transform(it) }
}
return characters
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.architect.coders.mu8.data.comics.model
package com.architect.coders.mu8.data.comics

import com.architect.coders.mu8.data.response.common.ThumbnailResponse
import com.architect.coders.mu8.data.response.common.ThumbnailEntity
import com.google.gson.annotations.SerializedName

data class ComicResponse(
Expand All @@ -17,5 +17,5 @@ data class ComicResponse(
val format: String,

@SerializedName("thumbnail")
val thumbnail: ThumbnailResponse
val thumbnail: ThumbnailEntity
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.architect.coders.mu8.data.comics

import com.architect.coders.mu8.data.comics.model.ComicResponse
import com.architect.coders.mu8.data.mapper.BaseResponseMapper
import com.architect.coders.mu8.data.utils.replaceHttps
import com.architect.codes.mu8.comics.Comic
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.architect.coders.mu8.data.database

import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import com.architect.coders.mu8.data.characters.CharactersDAO
import com.architect.coders.mu8.data.characters.CharactersEntity
import com.architect.coders.mu8.data.database.converter.ThumbnailTypeConverters
import com.architect.coders.mu8.data.database.converter.UrlsTypeConverters

private const val DATABASE_VERSION = 1

@Database(entities = [CharactersEntity::class], version = DATABASE_VERSION)
@TypeConverters(UrlsTypeConverters::class, ThumbnailTypeConverters::class)
abstract class MU8Database : RoomDatabase() {
abstract fun getCharactersDao(): CharactersDAO
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.architect.coders.mu8.data.database.converter

import androidx.room.TypeConverter
import com.architect.coders.mu8.data.response.common.ThumbnailEntity
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken

class ThumbnailTypeConverters {

private val gson = Gson()

@TypeConverter
fun stringToThumbnail(data: String?): ThumbnailEntity {
if (data == null) {
return ThumbnailEntity()
}
val type = object : TypeToken<ThumbnailEntity>() {}.type
return gson.fromJson(data, type)
}

@TypeConverter
fun thumbnailToString(thumbnail: ThumbnailEntity?): String {
if (thumbnail == null) {
return gson.toJson(ThumbnailEntity())
}
return gson.toJson(thumbnail)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.architect.coders.mu8.data.database.converter

import androidx.room.TypeConverter
import com.architect.coders.mu8.data.response.common.UrlsEntity
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken

class UrlsTypeConverters {

private val gson = Gson()

@TypeConverter
fun stringToUrls(data: String?): List<UrlsEntity> {
if (data == null) {
return emptyList()
}
val type = object : TypeToken<List<UrlsEntity>>() {}.type
return gson.fromJson(data, type)
}

@TypeConverter
fun urlsToString(urls: List<UrlsEntity>?): String {
if (urls.isNullOrEmpty()) {
gson.toJson(emptyList<UrlsEntity>())
}
return gson.toJson(urls)
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package com.architect.coders.mu8.data.mapper.common

import com.architect.coders.mu8.data.mapper.BaseResponseMapper
import com.architect.coders.mu8.data.response.common.UrlsResponse
import com.architect.coders.mu8.data.response.common.UrlsEntity
import com.architect.codes.mu8.common.Urls

class UrlsMapper : BaseResponseMapper<UrlsResponse, Urls>() {
class UrlsMapper : BaseResponseMapper<UrlsEntity, Urls>() {

override fun transform(input: UrlsResponse): Urls {
override fun transform(input: UrlsEntity): Urls {
return Urls(input.type, input.url)
}

fun transform(input: List<UrlsResponse>): List<Urls> {
fun transform(input: List<UrlsEntity>): List<Urls> {
val output = mutableListOf<Urls>()
input.forEach { output.add(transform(it)) }
return output
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.architect.coders.mu8.data.response.common

import com.architect.codes.mu8.utils.EMPTY_STRING

data class ThumbnailEntity(val path: String = EMPTY_STRING, val extension: String = EMPTY_STRING)

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.architect.coders.mu8.data.response.common

data class UrlsEntity(val type: String, val url: String)

This file was deleted.

Loading