书架性能优化

This commit is contained in:
HapeLee committed 2026-05-15 03:00:31 +08:00
1 parent 0c1ad67526
commit 5338313583
6 files changed
+2223 -29

No files matched your search

File diff suppressed because it is too large. Load diff
@@ -69,7 +69,7 @@ val appDb by lazy {
} }
@Database( @Database(
version = 86, version = 87,
exportSchema = true, exportSchema = true,
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class, entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class, ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
@@ -122,7 +122,8 @@ val appDb by lazy {
AutoMigration(from = 82, to = 83), AutoMigration(from = 82, to = 83),
AutoMigration(from = 83, to = 84), AutoMigration(from = 83, to = 84),
AutoMigration(from = 84, to = 85), AutoMigration(from = 84, to = 85),
AutoMigration(from = 85, to = 86) AutoMigration(from = 85, to = 86),
AutoMigration(from = 86, to = 87)
] ]
) )
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
@@ -33,7 +33,10 @@ import kotlin.math.max
@TypeConverters(Book.Converters::class) @TypeConverters(Book.Converters::class)
@Entity( @Entity(
tableName = "books", tableName = "books",
indices = [Index(value = ["name", "author"], unique = false)] indices = [
Index(value = ["name", "author"], unique = false),
Index(value = ["durChapterTime"], unique = false)
]
) )
data class Book( data class Book(
// 详情页Url(本地书源存储完整文件路径) // 详情页Url(本地书源存储完整文件路径)
@@ -262,15 +262,17 @@ fun BookshelfScreen(
) )
} }
) { paddingValues -> ) { paddingValues ->
EmptyMessage( if (!uiState.isInitialLoading) {
modifier = Modifier EmptyMessage(
.fillMaxSize() modifier = Modifier
.padding( .fillMaxSize()
top = paddingValues.calculateTopPadding(), .padding(
bottom = 120.dp top = paddingValues.calculateTopPadding(),
), bottom = 120.dp
messageResId = R.string.bookshelf_empty ),
) messageResId = R.string.bookshelf_empty
)
}
} }
return return
} }
@@ -1250,7 +1252,7 @@ fun BookshelfPage(
buttonText = stringResource(R.string.global_search), buttonText = stringResource(R.string.global_search),
onButtonClick = onGlobalSearch onButtonClick = onGlobalSearch
) )
} else { } else if (!uiState.isInitialLoading) {
EmptyMessage( EmptyMessage(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@@ -12,6 +12,7 @@ import kotlinx.collections.immutable.persistentSetOf
@Stable @Stable
data class BookshelfGroupSelectorState( data class BookshelfGroupSelectorState(
val isInitialLoading: Boolean = true,
val groups: ImmutableList<BookGroupUi> = persistentListOf(), val groups: ImmutableList<BookGroupUi> = persistentListOf(),
val selectedGroupIndex: Int = 0, val selectedGroupIndex: Int = 0,
val selectedGroupId: Long = BookGroup.IdAll val selectedGroupId: Long = BookGroup.IdAll
@@ -37,6 +38,7 @@ data class BookshelfUiState(
override val searchKey: String = "", override val searchKey: String = "",
override val isSearch: Boolean = false, override val isSearch: Boolean = false,
override val isLoading: Boolean = false, override val isLoading: Boolean = false,
val isInitialLoading: Boolean = true,
val groups: ImmutableList<BookGroupUi> = persistentListOf(), val groups: ImmutableList<BookGroupUi> = persistentListOf(),
val allGroups: ImmutableList<BookGroupUi> = persistentListOf(), val allGroups: ImmutableList<BookGroupUi> = persistentListOf(),
val groupPreviews: ImmutableMap<Long, ImmutableList<BookShelfItem>> = persistentMapOf(), val groupPreviews: ImmutableMap<Long, ImmutableList<BookShelfItem>> = persistentMapOf(),
@@ -77,10 +77,13 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
@@ -117,6 +120,7 @@ class BookshelfViewModel(
private val bookGroupStyleFlow = MutableStateFlow(BookshelfConfig.bookGroupStyle) private val bookGroupStyleFlow = MutableStateFlow(BookshelfConfig.bookGroupStyle)
private val draggingBooksFlow = MutableStateFlow<List<BookShelfItem>?>(null) private val draggingBooksFlow = MutableStateFlow<List<BookShelfItem>?>(null)
private val pendingSavedBooksFlow = MutableStateFlow<List<BookShelfItem>?>(null) private val pendingSavedBooksFlow = MutableStateFlow<List<BookShelfItem>?>(null)
private val isInitialLoadingFlow = MutableStateFlow(true)
private data class BookshelfSortConfig( private data class BookshelfSortConfig(
val sort: Int, val sort: Int,
@@ -156,6 +160,7 @@ class BookshelfViewModel(
val events = _eventChannel.receiveAsFlow() val events = _eventChannel.receiveAsFlow()
val groupsFlow: StateFlow<List<BookGroup>> = bookGroupRepository.flowShow() val groupsFlow: StateFlow<List<BookGroup>> = bookGroupRepository.flowShow()
.onEach { isInitialLoadingFlow.value = false }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList()) .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())
val allGroupsFlow: StateFlow<List<BookGroup>> = bookGroupRepository.flowAll() val allGroupsFlow: StateFlow<List<BookGroup>> = bookGroupRepository.flowAll()
@@ -363,18 +368,23 @@ class BookshelfViewModel(
) )
} }
private val groupPreviewsStateFlow = MutableStateFlow(
GroupPreviewState(persistentMapOf(), persistentMapOf(), 0)
)
private val allGroupBooksStateFlow = MutableStateFlow<ImmutableMap<Long, ImmutableList<BookShelfItem>>>(
persistentMapOf()
)
private val dataStateFlow = combine( private val dataStateFlow = combine(
combine( booksFlow,
booksFlow, groupsFlow,
groupsFlow, allGroupsFlow,
allGroupsFlow, groupPreviewsStateFlow,
groupPreviewsFlow, internalStateFlow
internalStateFlow ) { books, groups, allGroups, previews, internal ->
) { books, groups, allGroups, previews, internal -> BookshelfDataCore(books, groups, allGroups, previews, internal)
BookshelfDataCore(books, groups, allGroups, previews, internal) }.combine(allGroupBooksStateFlow) { core, allGroupBooks ->
},
allGroupBooksImmutableFlow
) { core, allGroupBooks ->
BookshelfDataState( BookshelfDataState(
books = core.books, books = core.books,
groups = core.groups.map { it.toBookGroupUi() }, groups = core.groups.map { it.toBookGroupUi() },
@@ -405,8 +415,9 @@ class BookshelfViewModel(
val uiState: StateFlow<BookshelfUiState> = combine( val uiState: StateFlow<BookshelfUiState> = combine(
dataStateFlow, dataStateFlow,
interactionStateFlow, interactionStateFlow,
visibleBooksFlow visibleBooksFlow,
) { data, interaction, filteredBooks -> isInitialLoadingFlow
) { data, interaction, filteredBooks, isInitialLoading ->
val books = data.books val books = data.books
val groups = data.groups val groups = data.groups
val allGroups = data.allGroups val allGroups = data.allGroups
@@ -429,6 +440,7 @@ class BookshelfViewModel(
BookshelfUiState( BookshelfUiState(
items = filteredBooks.toImmutableList(), items = filteredBooks.toImmutableList(),
selectedIds = selectedIds.toImmutableSet(), selectedIds = selectedIds.toImmutableSet(),
isInitialLoading = isInitialLoading,
groups = groups.toImmutableList(), groups = groups.toImmutableList(),
allGroups = allGroups.toImmutableList(), allGroups = allGroups.toImmutableList(),
groupPreviews = previews.previews, groupPreviews = previews.previews,
@@ -485,8 +497,19 @@ class BookshelfViewModel(
} }
} }
if (BookshelfConfig.autoRefreshBook) { viewModelScope.launch {
upAllBookToc() groupPreviewsFlow.collect { groupPreviewsStateFlow.value = it }
}
viewModelScope.launch {
allGroupBooksImmutableFlow.collect { allGroupBooksStateFlow.value = it }
}
viewModelScope.launch {
isInitialLoadingFlow.filter { !it }.collect {
if (BookshelfConfig.autoRefreshBook) {
upAllBookToc()
}
}
} }
} }