Skip to content

Commit

Permalink
Merge pull request #4 from cgpathos/RBP-19-caching
Browse files Browse the repository at this point in the history
[RBP-19] 로컬 캐싱 추가
  • Loading branch information
cgpathos authored Apr 30, 2024
2 parents 547f826 + 244b4a7 commit 37d0eef
Show file tree
Hide file tree
Showing 24 changed files with 562 additions and 64 deletions.
3 changes: 2 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:enableOnBackInvokedCallback="true"
android:theme="@style/Theme.Portfolio"
tools:targetApi="31">
tools:targetApi="33">
<activity
android:name=".core.MainActivity"
android:exported="true"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package today.pathos.android.portfolio.core.di

import android.content.Context
import androidx.room.Room
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import today.pathos.android.portfolio.data.datasource.local.db.CacheDatabase
import today.pathos.android.portfolio.data.datasource.local.db.dao.CharacterDao
import today.pathos.android.portfolio.data.datasource.local.db.dao.FameDao
import javax.inject.Singleton

@InstallIn(SingletonComponent::class)
@Module
class LocalModule {
@Singleton
@Provides
fun providesDatabase(@ApplicationContext context: Context): CacheDatabase =
Room.databaseBuilder(
context,
CacheDatabase::class.java,
"cache.db"
).build()

@Provides
fun providesFameDao(database: CacheDatabase): FameDao = database.fameDao()

@Provides
fun providesCharacterDao(database: CacheDatabase): CharacterDao = database.characterDao()
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import today.pathos.android.portfolio.data.repository.NetworkCharacterRepository
import today.pathos.android.portfolio.data.repository.NetworkFameRepository
import today.pathos.android.portfolio.data.repository.OfflineFirstCharacterRepository
import today.pathos.android.portfolio.data.repository.OfflineFirstFameRepository
import today.pathos.android.portfolio.domain.repository.CharacterRepository
import today.pathos.android.portfolio.domain.repository.FameRepository

@InstallIn(SingletonComponent::class)
@Module
abstract class DataModule {
abstract class RepositoryModule {
@Binds
abstract fun bindsFameRepository(
fameRepository: NetworkFameRepository,
fameRepository: OfflineFirstFameRepository,
): FameRepository

@Binds
abstract fun bindsCharacterRepository(
characterRepository: NetworkCharacterRepository,
characterRepository: OfflineFirstCharacterRepository,
): CharacterRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package today.pathos.android.portfolio.data.datasource.local

import today.pathos.android.portfolio.data.datasource.local.db.dao.CharacterDao
import today.pathos.android.portfolio.data.datasource.local.db.dao.FameDao
import today.pathos.android.portfolio.data.datasource.local.db.table.AvatarTbl
import today.pathos.android.portfolio.data.datasource.local.db.table.CharacterTbl
import today.pathos.android.portfolio.data.datasource.local.db.table.EquipmentTbl
import today.pathos.android.portfolio.data.datasource.local.db.table.FameTbl
import today.pathos.android.portfolio.data.datasource.remote.dto.res.ResAvatar
import today.pathos.android.portfolio.data.datasource.remote.dto.res.ResCharacter
import today.pathos.android.portfolio.data.datasource.remote.dto.res.ResEquipment
import today.pathos.android.portfolio.entity.Character
import javax.inject.Inject

class LocalDataSource @Inject constructor(
private val fameDao: FameDao,
private val characterDao: CharacterDao,
) {
suspend fun isFameListEmpty(): Boolean =
fameDao.fameListCount() == 0

suspend fun getFameList(): List<FameTbl> =
fameDao.getFameList()

suspend fun createFameList(characterList: List<ResCharacter>) {
fameDao.createFame(
fameList = characterList.map {
FameTbl(
serverId = checkNotNull(it.serverId),
characterId = it.characterId,
characterName = it.characterName,
characterImage = Character.getCharacterImageUrl(it.serverId, it.characterId, 3),
level = it.level,
jobId = it.jobId,
jobGrowId = it.jobGrowId,
jobName = it.jobName,
jobGrowName = it.jobGrowName,
fame = it.fame ?: 0,
)
}
)
}

suspend fun isCharacterEmpty(
serverId: String,
characterId: String,
): Boolean = characterDao.hasCharacter(serverId, characterId).not()

suspend fun getCharacter(
serverId: String,
characterId: String,
): CharacterTbl = characterDao.getCharacter(serverId, characterId)

suspend fun createCharacter(
serverId: String,
character: ResCharacter,
) {
characterDao.createCharacter(
CharacterTbl(
serverId = serverId,
characterId = character.characterId,
characterName = character.characterName,
characterImage = Character.getCharacterImageUrl(serverId, character.characterId, 3),
level = character.level,
jobId = character.jobId,
jobGrowId = character.jobGrowId,
jobName = character.jobName,
jobGrowName = character.jobGrowName,
fame = character.fame ?: 0,
)
)
}

suspend fun isCharacterEquipmentEmpty(
serverId: String,
characterId: String,
): Boolean = characterDao.hasCharacterEquipment(serverId, characterId).not()

suspend fun getCharacterEquipment(
serverId: String,
characterId: String,
): List<EquipmentTbl> = characterDao.getCharacterEquipment(serverId, characterId)

suspend fun createCharacterEquipment(
serverId: String,
characterId: String,
equipmentList: List<ResEquipment>,
) {
characterDao.upsertEquipment(
equipmentList.map {
EquipmentTbl(
serverId = serverId,
characterId = characterId,
slotId = it.slotId,
slotName = it.slotName,
itemId = it.itemId,
itemName = it.itemName,
itemTypeId = it.itemTypeId,
itemType = it.itemType,
itemTypeDetailId = it.itemTypeDetailId,
itemTypeDetail = it.itemTypeDetail,
itemAvailableLevel = it.itemAvailableLevel,
itemRarity = it.itemRarity,
setItemId = it.setItemId,
setItemName = it.setItemName,
reinforce = it.reinforce,
itemGradeName = it.itemGradeName,
amplificationName = it.amplificationName,
expiredDate = it.expiredDate,
refine = it.refine,
)
}
)
}

suspend fun isCharacterAvatarEmpty(
serverId: String,
characterId: String,
): Boolean = characterDao.hasCharacterAvatar(serverId, characterId).not()

suspend fun getCharacterAvatar(
serverId: String,
characterId: String,
): List<AvatarTbl> = characterDao.getCharacterAvatar(serverId, characterId)

suspend fun createCharacterAvatar(
serverId: String,
characterId: String,
equipmentList: List<ResAvatar>,
) {
characterDao.upsertAvatar(
equipmentList.map {
AvatarTbl(
serverId = serverId,
characterId = characterId,
slotId = it.slotId,
slotName = it.slotName,
itemId = it.itemId,
itemName = it.itemName,
cloneItemId = it.clone.itemId,
cloneItemName = it.clone.itemName,
itemRarity = it.itemRarity,
optionAbility = it.optionAbility
)
}
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package today.pathos.android.portfolio.data.datasource.local.db

import androidx.room.Database
import androidx.room.RoomDatabase
import today.pathos.android.portfolio.data.datasource.local.db.dao.CharacterDao
import today.pathos.android.portfolio.data.datasource.local.db.dao.FameDao
import today.pathos.android.portfolio.data.datasource.local.db.table.AvatarTbl
import today.pathos.android.portfolio.data.datasource.local.db.table.CharacterTbl
import today.pathos.android.portfolio.data.datasource.local.db.table.EquipmentTbl
import today.pathos.android.portfolio.data.datasource.local.db.table.FameTbl

@Database(
entities = [
FameTbl::class,
CharacterTbl::class,
EquipmentTbl::class,
AvatarTbl::class
],
version = 1
)
abstract class CacheDatabase : RoomDatabase() {
abstract fun fameDao(): FameDao
abstract fun characterDao(): CharacterDao
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package today.pathos.android.portfolio.data.datasource.local.db.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Upsert
import today.pathos.android.portfolio.data.datasource.local.db.table.AvatarTbl
import today.pathos.android.portfolio.data.datasource.local.db.table.CharacterTbl
import today.pathos.android.portfolio.data.datasource.local.db.table.EquipmentTbl

@Dao
abstract class CharacterDao {
@Insert
abstract suspend fun createCharacter(character: CharacterTbl)

@Query("SELECT 1 FROM CHARACTER_TBL WHERE server_id = :serverId and character_id = :characterId")
abstract suspend fun hasCharacter(
serverId: String,
characterId: String,
): Boolean

@Query("SELECT * FROM CHARACTER_TBL WHERE server_id = :serverId and character_id = :characterId")
abstract suspend fun getCharacter(
serverId: String,
characterId: String,
): CharacterTbl

@Upsert
abstract suspend fun upsertEquipment(equipmentList: List<EquipmentTbl>)

@Query("SELECT count(*) FROM EQUIPMENT_TBL WHERE server_id = :serverId and character_id = :characterId")
abstract suspend fun hasCharacterEquipment(
serverId: String,
characterId: String,
): Boolean

@Query("SELECT * FROM EQUIPMENT_TBL WHERE server_id = :serverId and character_id = :characterId")
abstract suspend fun getCharacterEquipment(
serverId: String,
characterId: String,
): List<EquipmentTbl>

@Upsert
abstract suspend fun upsertAvatar(equipmentList: List<AvatarTbl>)

@Query("SELECT count(*) FROM AVATAR_TBL WHERE server_id = :serverId and character_id = :characterId")
abstract suspend fun hasCharacterAvatar(
serverId: String,
characterId: String,
): Boolean

@Query("SELECT * FROM AVATAR_TBL WHERE server_id = :serverId and character_id = :characterId")
abstract suspend fun getCharacterAvatar(
serverId: String,
characterId: String,
): List<AvatarTbl>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package today.pathos.android.portfolio.data.datasource.local.db.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import today.pathos.android.portfolio.data.datasource.local.db.table.FameTbl

@Dao
abstract class FameDao {
@Insert
abstract suspend fun createFame(fameList: List<FameTbl>)

@Query("SELECT count(*) FROM FAME_TBL")
abstract suspend fun fameListCount(): Int

@Query("SELECT * FROM FAME_TBL")
abstract suspend fun getFameList(): List<FameTbl>

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package today.pathos.android.portfolio.data.datasource.local.db.table

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import today.pathos.android.portfolio.entity.AvatarSlotId
import today.pathos.android.portfolio.entity.EquipmentSlotId

@Entity(
tableName = "AVATAR_TBL",
primaryKeys = ["server_id", "character_id", "item_id"]
)
data class AvatarTbl(
@ColumnInfo(name = "server_id") val serverId: String,
@ColumnInfo(name = "character_id") val characterId: String,
@ColumnInfo(name = "item_id") val itemId: String,
@ColumnInfo(name = "item_name") val itemName: String,
@ColumnInfo(name = "slot_id") val slotId: AvatarSlotId,
@ColumnInfo(name = "slot_name") val slotName: String,
@ColumnInfo(name = "clone_item_id") val cloneItemId: String?,
@ColumnInfo(name = "clone_item_name") val cloneItemName: String?,
@ColumnInfo(name = "item_rarity") val itemRarity: String,
@ColumnInfo(name = "option_ability") val optionAbility: String?,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package today.pathos.android.portfolio.data.datasource.local.db.table

import androidx.room.ColumnInfo
import androidx.room.Entity

@Entity(
tableName = "CHARACTER_TBL",
primaryKeys = ["server_id", "character_id"]
)
data class CharacterTbl(
@ColumnInfo(name = "server_id") val serverId: String,
@ColumnInfo(name = "character_id") val characterId: String,
@ColumnInfo(name = "character_name") val characterName: String,
@ColumnInfo(name = "character_image") val characterImage: String,
@ColumnInfo(name = "level") val level: Int,
@ColumnInfo(name = "job_id") val jobId: String,
@ColumnInfo(name = "job_grow_id") val jobGrowId: String,
@ColumnInfo(name = "job_name") val jobName: String,
@ColumnInfo(name = "job_grow_name") val jobGrowName: String,
@ColumnInfo(name = "fame") val fame: Int = 0,
@ColumnInfo(name = "adventure_name") val adventureName: String? = null,
@ColumnInfo(name = "guild_id") val guildId: String? = null,
@ColumnInfo(name = "guild_name") val guildName: String? = null,
)
Loading

0 comments on commit 37d0eef

Please sign in to comment.