mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-14 12:57:04 +05:30
refactor(android): switch to DispatcherProvider
This commit is contained in:
parent
1db2f3256d
commit
59b35a9255
5 changed files with 61 additions and 13 deletions
|
@ -41,6 +41,7 @@ dependencies {
|
||||||
kapt(libs.dagger.hilt.compiler)
|
kapt(libs.dagger.hilt.compiler)
|
||||||
implementation(projects.api)
|
implementation(projects.api)
|
||||||
implementation(projects.common)
|
implementation(projects.common)
|
||||||
|
implementation(projects.coroutineUtils)
|
||||||
implementation(projects.database)
|
implementation(projects.database)
|
||||||
implementation(projects.metadataExtractor)
|
implementation(projects.metadataExtractor)
|
||||||
implementation(projects.model)
|
implementation(projects.model)
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package dev.msfjarvis.claw.android.injection
|
||||||
|
|
||||||
|
import dagger.Binds
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.Provides
|
||||||
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
import dev.msfjarvis.claw.util.coroutines.DefaultDispatcherProvider
|
||||||
|
import dev.msfjarvis.claw.util.coroutines.DispatcherProvider
|
||||||
|
import javax.inject.Qualifier
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@InstallIn(SingletonComponent::class)
|
||||||
|
abstract class CoroutineDispatcherModule {
|
||||||
|
|
||||||
|
@Binds abstract fun DefaultDispatcherProvider.bind(): DispatcherProvider
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@[Provides IODispatcher]
|
||||||
|
fun provideIODispatcher(dispatcherProvider: DispatcherProvider): CoroutineDispatcher {
|
||||||
|
return dispatcherProvider.io()
|
||||||
|
}
|
||||||
|
|
||||||
|
@[Provides DatabaseDispatcher]
|
||||||
|
fun provideDatabaseDispatcher(dispatcherProvider: DispatcherProvider): CoroutineDispatcher {
|
||||||
|
return dispatcherProvider.database()
|
||||||
|
}
|
||||||
|
|
||||||
|
@[Provides MainDispatcher]
|
||||||
|
fun provideMainDispatcher(dispatcherProvider: DispatcherProvider): CoroutineDispatcher {
|
||||||
|
return dispatcherProvider.main()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class DatabaseDispatcher
|
||||||
|
|
||||||
|
@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class MainDispatcher
|
||||||
|
|
||||||
|
@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class IODispatcher
|
|
@ -3,17 +3,18 @@ package dev.msfjarvis.claw.android.paging
|
||||||
import androidx.paging.PagingSource
|
import androidx.paging.PagingSource
|
||||||
import androidx.paging.PagingState
|
import androidx.paging.PagingState
|
||||||
import dev.msfjarvis.claw.model.LobstersPost
|
import dev.msfjarvis.claw.model.LobstersPost
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class LobstersPagingSource(
|
class LobstersPagingSource(
|
||||||
private val getMorePosts: suspend (Int) -> List<LobstersPost>,
|
private val getMorePosts: suspend (Int) -> List<LobstersPost>,
|
||||||
|
private val ioDispatcher: CoroutineDispatcher,
|
||||||
) : PagingSource<Int, LobstersPost>() {
|
) : PagingSource<Int, LobstersPost>() {
|
||||||
|
|
||||||
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LobstersPost> {
|
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LobstersPost> {
|
||||||
return try {
|
return try {
|
||||||
val page = params.key ?: 1
|
val page = params.key ?: 1
|
||||||
val posts = withContext(Dispatchers.IO) { getMorePosts(page) }
|
val posts = withContext(ioDispatcher) { getMorePosts(page) }
|
||||||
|
|
||||||
LoadResult.Page(
|
LoadResult.Page(
|
||||||
data = posts,
|
data = posts,
|
||||||
|
|
|
@ -5,12 +5,13 @@ import androidx.lifecycle.viewModelScope
|
||||||
import androidx.paging.Pager
|
import androidx.paging.Pager
|
||||||
import androidx.paging.PagingConfig
|
import androidx.paging.PagingConfig
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import dev.msfjarvis.claw.android.injection.IODispatcher
|
||||||
import dev.msfjarvis.claw.android.paging.LobstersPagingSource
|
import dev.msfjarvis.claw.android.paging.LobstersPagingSource
|
||||||
import dev.msfjarvis.claw.android.ui.toLocalDateTime
|
import dev.msfjarvis.claw.android.ui.toLocalDateTime
|
||||||
import dev.msfjarvis.claw.api.LobstersApi
|
import dev.msfjarvis.claw.api.LobstersApi
|
||||||
import dev.msfjarvis.claw.database.local.SavedPost
|
import dev.msfjarvis.claw.database.local.SavedPost
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -24,16 +25,19 @@ constructor(
|
||||||
private val api: LobstersApi,
|
private val api: LobstersApi,
|
||||||
private val savedPostsRepository: SavedPostsRepository,
|
private val savedPostsRepository: SavedPostsRepository,
|
||||||
private val postDetailsRepository: PostDetailsRepository,
|
private val postDetailsRepository: PostDetailsRepository,
|
||||||
|
@IODispatcher private val ioDispatcher: CoroutineDispatcher,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
private var hottestPostsPagingSource: LobstersPagingSource? = null
|
private var hottestPostsPagingSource: LobstersPagingSource? = null
|
||||||
private var newestPostsPagingSource: LobstersPagingSource? = null
|
private var newestPostsPagingSource: LobstersPagingSource? = null
|
||||||
private val hottestPostsPager =
|
private val hottestPostsPager =
|
||||||
Pager(PagingConfig(20)) {
|
Pager(PagingConfig(20)) {
|
||||||
LobstersPagingSource(api::getHottestPosts).also { hottestPostsPagingSource = it }
|
LobstersPagingSource(api::getHottestPosts, ioDispatcher).also {
|
||||||
|
hottestPostsPagingSource = it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private val newestPostsPager =
|
private val newestPostsPager =
|
||||||
Pager(PagingConfig(20)) {
|
Pager(PagingConfig(20)) {
|
||||||
LobstersPagingSource(api::getNewestPosts).also { newestPostsPagingSource = it }
|
LobstersPagingSource(api::getNewestPosts, ioDispatcher).also { newestPostsPagingSource = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
val hottestPosts
|
val hottestPosts
|
||||||
|
@ -58,7 +62,7 @@ constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toggleSave(post: SavedPost) {
|
fun toggleSave(post: SavedPost) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(ioDispatcher) {
|
||||||
val saved = isPostSaved(post)
|
val saved = isPostSaved(post)
|
||||||
if (saved) {
|
if (saved) {
|
||||||
savedPostsRepository.removePost(post)
|
savedPostsRepository.removePost(post)
|
||||||
|
@ -69,14 +73,13 @@ constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getPostComments(postId: String) =
|
suspend fun getPostComments(postId: String) =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(ioDispatcher) {
|
||||||
val details = api.getPostDetails(postId)
|
val details = api.getPostDetails(postId)
|
||||||
val extendedDetails = postDetailsRepository.getExtendedDetails(details)
|
val extendedDetails = postDetailsRepository.getExtendedDetails(details)
|
||||||
extendedDetails
|
extendedDetails
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getUserProfile(username: String) =
|
suspend fun getUserProfile(username: String) = withContext(ioDispatcher) { api.getUser(username) }
|
||||||
withContext(Dispatchers.IO) { api.getUser(username) }
|
|
||||||
|
|
||||||
fun refreshHottestPosts() {
|
fun refreshHottestPosts() {
|
||||||
hottestPostsPagingSource?.invalidate()
|
hottestPostsPagingSource?.invalidate()
|
||||||
|
|
|
@ -2,29 +2,31 @@ package dev.msfjarvis.claw.android.viewmodel
|
||||||
|
|
||||||
import app.cash.sqldelight.coroutines.asFlow
|
import app.cash.sqldelight.coroutines.asFlow
|
||||||
import app.cash.sqldelight.coroutines.mapToList
|
import app.cash.sqldelight.coroutines.mapToList
|
||||||
|
import dev.msfjarvis.claw.android.injection.DatabaseDispatcher
|
||||||
import dev.msfjarvis.claw.database.LobstersDatabase
|
import dev.msfjarvis.claw.database.LobstersDatabase
|
||||||
import dev.msfjarvis.claw.database.local.SavedPost
|
import dev.msfjarvis.claw.database.local.SavedPost
|
||||||
import io.github.aakira.napier.Napier
|
import io.github.aakira.napier.Napier
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class SavedPostsRepository
|
class SavedPostsRepository
|
||||||
@Inject
|
@Inject
|
||||||
constructor(
|
constructor(
|
||||||
database: LobstersDatabase,
|
database: LobstersDatabase,
|
||||||
|
@DatabaseDispatcher private val dbDispatcher: CoroutineDispatcher,
|
||||||
) {
|
) {
|
||||||
private val savedPostQueries = database.savedPostQueries
|
private val savedPostQueries = database.savedPostQueries
|
||||||
val savedPosts = savedPostQueries.selectAllPosts().asFlow().mapToList()
|
val savedPosts = savedPostQueries.selectAllPosts().asFlow().mapToList(dbDispatcher)
|
||||||
|
|
||||||
suspend fun savePost(post: SavedPost) {
|
suspend fun savePost(post: SavedPost) {
|
||||||
Napier.d(tag = TAG) { "Saving post: ${post.shortId}" }
|
Napier.d(tag = TAG) { "Saving post: ${post.shortId}" }
|
||||||
withContext(Dispatchers.IO) { savedPostQueries.insertOrReplacePost(post) }
|
withContext(dbDispatcher) { savedPostQueries.insertOrReplacePost(post) }
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun removePost(post: SavedPost) {
|
suspend fun removePost(post: SavedPost) {
|
||||||
Napier.d(tag = TAG) { "Removing post: ${post.shortId}" }
|
Napier.d(tag = TAG) { "Removing post: ${post.shortId}" }
|
||||||
withContext(Dispatchers.IO) { savedPostQueries.deletePost(post.shortId) }
|
withContext(dbDispatcher) { savedPostQueries.deletePost(post.shortId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue