pref: 性能优化

This commit is contained in:
HuanCheng65 2023-07-24 10:45:45 +08:00
parent ad2ea7eefd
commit c7c646d7de
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
4 changed files with 32 additions and 53 deletions

View File

@ -8,40 +8,11 @@ import kotlinx.collections.immutable.toImmutableList
@Stable @Stable
class StableHolder<T>(val item: T) { class StableHolder<T>(val item: T) {
operator fun component1(): T = item operator fun component1(): T = item
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as StableHolder<*>
if (item != other.item) return false
return true
}
override fun hashCode(): Int {
return item?.hashCode() ?: 0
}
} }
@Immutable @Immutable
class ImmutableHolder<T>(val item: T) { class ImmutableHolder<T>(val item: T) {
operator fun component1(): T = item operator fun component1(): T = item
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as ImmutableHolder<*>
if (item != other.item) return false
return true
}
override fun hashCode(): Int {
return item?.hashCode() ?: 0
}
@Stable @Stable
fun get(): T = item fun get(): T = item

View File

@ -42,11 +42,13 @@ import com.huanchengfly.tieba.post.ui.widgets.compose.ClickMenu
import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalGrid import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalGrid
import com.huanchengfly.tieba.post.ui.widgets.compose.items import com.huanchengfly.tieba.post.ui.widgets.compose.items
import com.huanchengfly.tieba.post.ui.widgets.compose.rememberMenuState import com.huanchengfly.tieba.post.ui.widgets.compose.rememberMenuState
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@Composable @Composable
fun Dislike( fun Dislike(
personalized: ImmutableHolder<ThreadPersonalized>, personalized: ImmutableHolder<ThreadPersonalized>,
onDislike: (clickTime: Long, reasons: List<ImmutableHolder<DislikeReason>>) -> Unit, onDislike: (clickTime: Long, reasons: ImmutableList<ImmutableHolder<DislikeReason>>) -> Unit,
) { ) {
var clickTime by remember { mutableStateOf(0L) } var clickTime by remember { mutableStateOf(0L) }
val selectedReasons = remember { mutableStateListOf<ImmutableHolder<DislikeReason>>() } val selectedReasons = remember { mutableStateListOf<ImmutableHolder<DislikeReason>>() }
@ -88,7 +90,7 @@ fun Dislike(
.background(color = ExtendedTheme.colors.primary) .background(color = ExtendedTheme.colors.primary)
.clickable { .clickable {
dismiss() dismiss()
onDislike(clickTime, selectedReasons) onDislike(clickTime, selectedReasons.toImmutableList())
} }
.padding(vertical = 4.dp, horizontal = 8.dp), .padding(vertical = 4.dp, horizontal = 8.dp),
color = ExtendedTheme.colors.onAccent, color = ExtendedTheme.colors.onAccent,

View File

@ -67,6 +67,8 @@ import com.huanchengfly.tieba.post.ui.widgets.compose.FeedCard
import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoad import com.huanchengfly.tieba.post.ui.widgets.compose.LazyLoad
import com.huanchengfly.tieba.post.ui.widgets.compose.LoadMoreLayout import com.huanchengfly.tieba.post.ui.widgets.compose.LoadMoreLayout
import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalDivider import com.huanchengfly.tieba.post.ui.widgets.compose.VerticalDivider
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -94,11 +96,11 @@ fun PersonalizedPage(
) )
val data by viewModel.uiState.collectPartialAsState( val data by viewModel.uiState.collectPartialAsState(
prop1 = PersonalizedUiState::data, prop1 = PersonalizedUiState::data,
initial = emptyList() initial = persistentListOf()
) )
val threadPersonalizedData by viewModel.uiState.collectPartialAsState( val threadPersonalizedData by viewModel.uiState.collectPartialAsState(
prop1 = PersonalizedUiState::threadPersonalizedData, prop1 = PersonalizedUiState::threadPersonalizedData,
initial = emptyList() initial = persistentListOf()
) )
val refreshPosition by viewModel.uiState.collectPartialAsState( val refreshPosition by viewModel.uiState.collectPartialAsState(
prop1 = PersonalizedUiState::refreshPosition, prop1 = PersonalizedUiState::refreshPosition,
@ -106,7 +108,7 @@ fun PersonalizedPage(
) )
val hiddenThreadIds by viewModel.uiState.collectPartialAsState( val hiddenThreadIds by viewModel.uiState.collectPartialAsState(
prop1 = PersonalizedUiState::hiddenThreadIds, prop1 = PersonalizedUiState::hiddenThreadIds,
initial = emptyList() initial = persistentListOf()
) )
val pullRefreshState = rememberPullRefreshState( val pullRefreshState = rememberPullRefreshState(
refreshing = isRefreshing, refreshing = isRefreshing,
@ -246,14 +248,14 @@ private fun BoxScope.RefreshTip(refreshCount: Int) {
@Composable @Composable
private fun FeedList( private fun FeedList(
state: LazyListState, state: LazyListState,
dataProvider: () -> List<ImmutableHolder<ThreadInfo>>, dataProvider: () -> ImmutableList<ImmutableHolder<ThreadInfo>>,
personalizedDataProvider: () -> List<ImmutableHolder<ThreadPersonalized>?>, personalizedDataProvider: () -> ImmutableList<ImmutableHolder<ThreadPersonalized>?>,
refreshPositionProvider: () -> Int, refreshPositionProvider: () -> Int,
hiddenThreadIdsProvider: () -> List<Long>, hiddenThreadIdsProvider: () -> ImmutableList<Long>,
onItemClick: (ThreadInfo) -> Unit, onItemClick: (ThreadInfo) -> Unit,
onItemReplyClick: (ThreadInfo) -> Unit, onItemReplyClick: (ThreadInfo) -> Unit,
onAgree: (ThreadInfo) -> Unit, onAgree: (ThreadInfo) -> Unit,
onDislike: (ThreadInfo, Long, List<ImmutableHolder<DislikeReason>>) -> Unit, onDislike: (ThreadInfo, Long, ImmutableList<ImmutableHolder<DislikeReason>>) -> Unit,
onRefresh: () -> Unit, onRefresh: () -> Unit,
onOpenForum: (forumName: String) -> Unit = {}, onOpenForum: (forumName: String) -> Unit = {},
) { ) {
@ -312,9 +314,11 @@ private fun FeedList(
onClick = onItemClick, onClick = onItemClick,
onReplyClick = onItemReplyClick, onReplyClick = onItemReplyClick,
onAgree = onAgree, onAgree = onAgree,
onClickForum = { onClickForum = remember {
{
onOpenForum(it.name) onOpenForum(it.name)
} }
}
) { ) {
if (personalized != null) { if (personalized != null) {
Dislike( Dislike(

View File

@ -22,6 +22,9 @@ import com.huanchengfly.tieba.post.arch.wrapImmutable
import com.huanchengfly.tieba.post.models.DislikeBean import com.huanchengfly.tieba.post.models.DislikeBean
import com.huanchengfly.tieba.post.utils.appPreferences import com.huanchengfly.tieba.post.utils.appPreferences
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
@ -30,7 +33,6 @@ import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import okhttp3.internal.toImmutableList
import javax.inject.Inject import javax.inject.Inject
@Stable @Stable
@ -156,8 +158,8 @@ sealed interface PersonalizedPartialChange : PartialChange<PersonalizedUiState>
sealed class Agree private constructor() : PersonalizedPartialChange { sealed class Agree private constructor() : PersonalizedPartialChange {
private fun List<ImmutableHolder<ThreadInfo>>.updateAgreeStatus( private fun List<ImmutableHolder<ThreadInfo>>.updateAgreeStatus(
threadId: Long, threadId: Long,
hasAgree: Int hasAgree: Int,
): List<ImmutableHolder<ThreadInfo>> { ): ImmutableList<ImmutableHolder<ThreadInfo>> {
return map { return map {
val threadInfo = it.get() val threadInfo = it.get()
if (threadInfo.threadId == threadId) { if (threadInfo.threadId == threadId) {
@ -193,7 +195,7 @@ sealed interface PersonalizedPartialChange : PartialChange<PersonalizedUiState>
} else { } else {
threadInfo threadInfo
} }
}.map { wrapImmutable(it) } }.wrapImmutable()
} }
override fun reduce(oldState: PersonalizedUiState): PersonalizedUiState = override fun reduce(oldState: PersonalizedUiState): PersonalizedUiState =
@ -231,14 +233,14 @@ sealed interface PersonalizedPartialChange : PartialChange<PersonalizedUiState>
when (this) { when (this) {
is Start -> { is Start -> {
if (!oldState.hiddenThreadIds.contains(threadId)) { if (!oldState.hiddenThreadIds.contains(threadId)) {
oldState.copy(hiddenThreadIds = oldState.hiddenThreadIds + threadId) oldState.copy(hiddenThreadIds = (oldState.hiddenThreadIds + threadId).toImmutableList())
} else { } else {
oldState oldState
} }
} }
is Success -> { is Success -> {
if (!oldState.hiddenThreadIds.contains(threadId)) { if (!oldState.hiddenThreadIds.contains(threadId)) {
oldState.copy(hiddenThreadIds = oldState.hiddenThreadIds + threadId) oldState.copy(hiddenThreadIds = (oldState.hiddenThreadIds + threadId).toImmutableList())
} else { } else {
oldState oldState
} }
@ -267,8 +269,8 @@ sealed interface PersonalizedPartialChange : PartialChange<PersonalizedUiState>
is Success -> oldState.copy( is Success -> oldState.copy(
isRefreshing = false, isRefreshing = false,
currentPage = 1, currentPage = 1,
data = data + oldState.data, data = (data + oldState.data).toImmutableList(),
threadPersonalizedData = threadPersonalizedData + oldState.threadPersonalizedData, threadPersonalizedData = (threadPersonalizedData + oldState.threadPersonalizedData).toImmutableList(),
refreshPosition = if (oldState.data.isEmpty()) 0 else data.size refreshPosition = if (oldState.data.isEmpty()) 0 else data.size
) )
is Failure -> oldState.copy(isRefreshing = false) is Failure -> oldState.copy(isRefreshing = false)
@ -293,8 +295,8 @@ sealed interface PersonalizedPartialChange : PartialChange<PersonalizedUiState>
is Success -> oldState.copy( is Success -> oldState.copy(
isLoadingMore = false, isLoadingMore = false,
currentPage = currentPage, currentPage = currentPage,
data = oldState.data + data, data = (oldState.data + data).toImmutableList(),
threadPersonalizedData = oldState.threadPersonalizedData + threadPersonalizedData, threadPersonalizedData = (oldState.threadPersonalizedData + threadPersonalizedData).toImmutableList(),
) )
is Failure -> oldState.copy(isLoadingMore = false) is Failure -> oldState.copy(isLoadingMore = false)
} }
@ -318,9 +320,9 @@ data class PersonalizedUiState(
val isRefreshing: Boolean = true, val isRefreshing: Boolean = true,
val isLoadingMore: Boolean = false, val isLoadingMore: Boolean = false,
val currentPage: Int = 1, val currentPage: Int = 1,
val data: List<ImmutableHolder<ThreadInfo>> = emptyList(), val data: ImmutableList<ImmutableHolder<ThreadInfo>> = persistentListOf(),
val threadPersonalizedData: List<ImmutableHolder<ThreadPersonalized>?> = emptyList(), val threadPersonalizedData: ImmutableList<ImmutableHolder<ThreadPersonalized>?> = persistentListOf(),
val hiddenThreadIds: List<Long> = emptyList(), val hiddenThreadIds: ImmutableList<Long> = persistentListOf(),
val refreshPosition: Int = 0, val refreshPosition: Int = 0,
): UiState ): UiState