-
Notifications
You must be signed in to change notification settings - Fork 8
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
[AN/USER] 축제 목록 캐싱 적용 (#591) #592
Changes from all commits
ecd0941
3adad04
4f267f9
078890b
78b436a
9db984d
65e05cb
cd364a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package com.festago.festago.data.dao | ||
|
||
import android.content.Context | ||
import androidx.room.Database | ||
import androidx.room.Room | ||
import androidx.room.RoomDatabase | ||
|
||
@Database( | ||
entities = [ | ||
FestivalEntity::class, | ||
], | ||
version = 1, | ||
exportSchema = true, | ||
) | ||
abstract class FestagoDatabase : RoomDatabase() { | ||
abstract fun festivalDao(): FestivalDao | ||
|
||
companion object { | ||
private const val DATABASE_NAME = "festago.db" | ||
|
||
fun buildDatabase(context: Context): FestagoDatabase { | ||
return Room.databaseBuilder( | ||
context, | ||
FestagoDatabase::class.java, | ||
DATABASE_NAME, | ||
).build() | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.festago.festago.data.dao | ||
|
||
import androidx.room.Dao | ||
import androidx.room.Insert | ||
import androidx.room.OnConflictStrategy | ||
import androidx.room.Query | ||
import kotlinx.coroutines.flow.Flow | ||
|
||
@Dao | ||
interface FestivalDao { | ||
@Query("SELECT * FROM festivals") | ||
fun getFestivals(): Flow<List<FestivalEntity>> | ||
|
||
@Insert(onConflict = OnConflictStrategy.REPLACE) | ||
fun insertFestivals(festivals: List<FestivalEntity>): List<Long> | ||
|
||
@Query("DELETE FROM festivals") | ||
fun clearFestivals() | ||
|
||
fun replaceFestivals(festivals: List<FestivalEntity>): List<Long> { | ||
clearFestivals() | ||
return insertFestivals(festivals) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.festago.festago.data.dao | ||
|
||
import androidx.room.Entity | ||
import androidx.room.PrimaryKey | ||
|
||
@Entity(tableName = "festivals") | ||
data class FestivalEntity( | ||
@PrimaryKey | ||
val id: Int, | ||
val schoolId: Int, | ||
val name: String, | ||
val startDate: String, | ||
val endDate: String, | ||
val thumbnail: String, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.festago.festago.data.dao.mapper | ||
|
||
import com.festago.festago.data.dao.FestivalEntity | ||
import com.festago.festago.model.Festival | ||
import java.time.LocalDate | ||
|
||
fun List<FestivalEntity>.toDomain() = map(FestivalEntity::toDomain) | ||
|
||
fun FestivalEntity.toDomain() = Festival( | ||
id = id.toLong(), | ||
name = name, | ||
startDate = LocalDate.parse(startDate), | ||
endDate = LocalDate.parse(endDate), | ||
thumbnail = thumbnail, | ||
) | ||
|
||
fun List<Festival>.toEntity() = map(Festival::toEntity) | ||
|
||
fun Festival.toEntity() = FestivalEntity( | ||
id = this.id.toInt(), | ||
schoolId = -1, | ||
name = this.name, | ||
startDate = this.startDate.toString(), | ||
endDate = this.endDate.toString(), | ||
thumbnail = this.thumbnail, | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.festago.festago.data.di.singletonscope | ||
|
||
import android.content.Context | ||
import com.festago.festago.data.dao.FestagoDatabase | ||
import com.festago.festago.data.dao.FestivalDao | ||
import dagger.Module | ||
import dagger.Provides | ||
import dagger.hilt.InstallIn | ||
import dagger.hilt.android.qualifiers.ApplicationContext | ||
import dagger.hilt.components.SingletonComponent | ||
|
||
@InstallIn(SingletonComponent::class) | ||
@Module | ||
object DaoModule { | ||
@Provides | ||
fun provideFestivalDao(@ApplicationContext context: Context): FestivalDao = | ||
FestagoDatabase.buildDatabase(context).festivalDao() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,26 +28,34 @@ class FestivalListViewModel @Inject constructor( | |
private val _event = MutableSharedFlow<FestivalListEvent>() | ||
val event: SharedFlow<FestivalListEvent> = _event.asSharedFlow() | ||
|
||
init { | ||
viewModelScope.launch { | ||
festivalRepository.festivals.collect { | ||
_uiState.value = FestivalListUiState.Success( | ||
festivals = it.map { festival -> | ||
FestivalItemUiState( | ||
id = festival.id, | ||
name = festival.name, | ||
startDate = festival.startDate, | ||
endDate = festival.endDate, | ||
thumbnail = festival.thumbnail, | ||
onFestivalDetail = ::showTicketReserve, | ||
) | ||
Comment on lines
+34
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 개인적으로 private 함수로 분리했으면 좋겠습니당 |
||
}, | ||
) | ||
} | ||
} | ||
} | ||
|
||
fun loadFestivals() { | ||
viewModelScope.launch { | ||
festivalRepository.loadFestivals() | ||
.onSuccess { | ||
_uiState.value = FestivalListUiState.Success( | ||
festivals = it.map { festival -> | ||
FestivalItemUiState( | ||
id = festival.id, | ||
name = festival.name, | ||
startDate = festival.startDate, | ||
endDate = festival.endDate, | ||
thumbnail = festival.thumbnail, | ||
onFestivalDetail = ::showTicketReserve, | ||
) | ||
}, | ||
) | ||
}.onFailure { | ||
_uiState.value = FestivalListUiState.Error | ||
analyticsHelper.logNetworkFailure(KEY_LOAD_FESTIVALS_LOG, it.message.toString()) | ||
} | ||
festivalRepository.loadFestivals().onFailure { | ||
_uiState.value = FestivalListUiState.Error | ||
analyticsHelper.logNetworkFailure( | ||
KEY_LOAD_FESTIVALS_LOG, | ||
it.message.toString(), | ||
) | ||
} | ||
Comment on lines
+52
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Room 써서 캐싱까지 할거면 Error 상태일 때도 캐싱된 데이터를 보여주면 좋을 것 같은데 이 부분 상태나 이벤트 처리 어떻게 할지 얘기 해봐야할 것 같아요! |
||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,11 @@ package com.festago.festago.repository | |
|
||
import com.festago.festago.model.Festival | ||
import com.festago.festago.model.Reservation | ||
import kotlinx.coroutines.flow.Flow | ||
|
||
interface FestivalRepository { | ||
val festivals: Flow<List<Festival>> | ||
|
||
suspend fun loadFestivals(): Result<List<Festival>> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 실패 처리만 하고있어서 Result 만 반환해도 될 것 같네요 |
||
suspend fun loadFestivalDetail(festivalId: Long): Result<Reservation> | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
서버에 새 데이터를 요청해서 불러오는 동안에 캐싱해둔 데이터를 보여줄 수 있고 좋네요 👍
(몰라서 하는 질문) 매번 내장 DB 테이블 전체를 Delete하고 Insert 하는 건 성능상 문제가 없나요??