src: remove cache and simplify db logic

Signed-off-by: Aditya Wasan <adityawasan55@gmail.com>
This commit is contained in:
Aditya Wasan 2021-01-24 23:19:07 +05:30 committed by Harsh Shandilya
parent 3bcdcbdac7
commit f9fcb089a1
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
7 changed files with 60 additions and 23 deletions

View file

@ -14,9 +14,17 @@ class LobstersPagingSource @Inject constructor(
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LobstersPost> {
return try {
val page = params.key ?: 1
val savedPosts = lobstersRepository.getCachedPosts()
val posts = lobstersApi.getHottestPosts(page).map { post ->
post.copy(is_saved = savedPosts.contains(post.short_id))
// We can replace these two lines below with a getOrInsertPost repository method.
val dbPost = lobstersRepository.getPost(post.short_id)
return@map if (dbPost == null) {
// If db does not contain the post, add it and return the original post
lobstersRepository.addPostToDB(post)
post
} else {
// Otherwise return the db post
dbPost
}
}
LoadResult.Page(

View file

@ -8,32 +8,33 @@ import javax.inject.Inject
class LobstersRepository @Inject constructor(private val lobstersDatabase: LobstersDatabase) {
private var savedPostCache: MutableSet<String>? = null
fun isPostSaved(postId: String): Boolean {
savedPostCache ?: return false
return requireNotNull(savedPostCache).contains(postId)
// returns the post if it exists and its is_saved property is true
val post = lobstersDatabase.postQueries.isPostSaved(postId).executeAsOneOrNull()
return post != null
}
suspend fun getPost(postId: String): LobstersPost? = withContext(Dispatchers.IO) {
return@withContext lobstersDatabase.postQueries.selectPost(postId).executeAsOneOrNull()
}
suspend fun getSavedPosts(): List<LobstersPost> = withContext(Dispatchers.IO) {
return@withContext lobstersDatabase.postQueries.selectSavedPosts().executeAsList()
}
suspend fun addPostToDB(post: LobstersPost) = withContext(Dispatchers.IO) {
lobstersDatabase.postQueries.insertOrReplacePost(post)
}
suspend fun savePost(post: LobstersPost) = withContext(Dispatchers.IO) {
val isElementAdded = getCachedPosts().add(post.short_id)
if (isElementAdded) {
if (!isPostSaved(post.short_id)) {
lobstersDatabase.postQueries.savePost(post.short_id)
}
}
suspend fun removeSavedPost(post: LobstersPost) = withContext(Dispatchers.IO) {
val isElementRemoved = getCachedPosts().remove(post.short_id)
if (isElementRemoved) {
if (isPostSaved(post.short_id)) {
lobstersDatabase.postQueries.removeSavedPost(post.short_id)
}
}
suspend fun getCachedPosts(): MutableSet<String> = withContext(Dispatchers.IO) {
if (savedPostCache != null) return@withContext requireNotNull(savedPostCache)
val dbPosts = lobstersDatabase.postQueries.selectSavedPosts().executeAsList()
savedPostCache = dbPosts.filter { it.is_saved ?: false }.map { it.short_id }.toMutableSet()
return@withContext requireNotNull(savedPostCache)
}
}

View file

@ -12,17 +12,20 @@ import dev.msfjarvis.lobsters.data.local.LobstersPost
import dev.msfjarvis.lobsters.database.LobstersDatabase
import dev.msfjarvis.lobsters.model.SubmitterAdapter
import dev.msfjarvis.lobsters.model.TagsAdapter
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
@Provides
@Singleton
fun providesSqlDriver(@ApplicationContext context: Context): SqlDriver {
return AndroidSqliteDriver(LobstersDatabase.Schema, context)
}
@Provides
@Singleton
fun providesLobstersDatabase(sqlDriver: SqlDriver): LobstersDatabase {
return LobstersDatabase(sqlDriver, LobstersPost.Adapter(SubmitterAdapter(), TagsAdapter()))
}

View file

@ -64,6 +64,8 @@ fun LobstersApp() {
val savedPosts by viewModel.savedPosts.collectAsState()
val hottestPostsListState = rememberLazyListState()
viewModel.getSavedPosts()
Scaffold(
bottomBar = {
LobstersBottomNav(

View file

@ -14,6 +14,10 @@ import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
@ -65,6 +69,8 @@ fun LobstersItem(
onLongClick: () -> Unit,
onSaveButtonClick: () -> Unit,
) {
var isSaved by remember { mutableStateOf(post.is_saved ?: false) }
Surface(
modifier = Modifier
.fillMaxWidth()
@ -121,11 +127,14 @@ fun LobstersItem(
},
)
IconResource(
resourceId = if (post.is_saved == true) R.drawable.ic_favorite_24px else R.drawable.ic_favorite_border_24px,
resourceId = if (isSaved) R.drawable.ic_favorite_24px else R.drawable.ic_favorite_border_24px,
modifier = Modifier
.padding(8.dp)
.clickable(
onClick = onSaveButtonClick,
onClick = {
onSaveButtonClick()
isSaved = isSaved.not()
},
indication = rememberRipple(),
)
.constrainAs(saveButton) {

View file

@ -20,7 +20,7 @@ class LobstersViewModel @Inject constructor(
) : ViewModel() {
private val _savedPosts = MutableStateFlow<List<LobstersPost>>(emptyList())
val savedPosts = _savedPosts.asStateFlow()
val posts = Pager(PagingConfig(25)) {
val posts = Pager(PagingConfig(5)) {
pagingSource
}.flow
@ -31,17 +31,25 @@ class LobstersViewModel @Inject constructor(
}
}
fun getSavedPosts() {
viewModelScope.launch {
lobstersRepository.getSavedPosts().forEach {
_savedPosts.value = _savedPosts.value + it
}
}
}
private fun savePost(post: LobstersPost) {
viewModelScope.launch {
lobstersRepository.savePost(post)
_savedPosts.value = _savedPosts.value + post
_savedPosts.value = _savedPosts.value + post.copy(is_saved = true)
}
}
private fun removeSavedPost(post: LobstersPost) {
viewModelScope.launch {
lobstersRepository.removeSavedPost(post)
_savedPosts.value = _savedPosts.value - post
_savedPosts.value = _savedPosts.value - post.copy(is_saved = true)
}
}
}

View file

@ -56,6 +56,12 @@ deleteAllPosts:
DELETE
FROM LobstersPost;
isPostSaved:
SELECT *
FROM LobstersPost
WHERE short_id = ?
AND is_saved = 1;
selectCount:
SELECT COUNT(*)
FROM LobstersPost;