pref(MainActivity): 优化主页面性能 (#209)

Reduce unnecessary recomposition, removed unnecessary "remember", and merged Background and Surface components.
This commit is contained in:
Oxy 2023-09-24 00:54:57 +08:00 committed by GitHub
parent 6527155925
commit 2b3dd20f65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 120 additions and 102 deletions

View File

@ -19,7 +19,6 @@ import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.VisibilityThreshold import androidx.compose.animation.core.VisibilityThreshold
import androidx.compose.animation.core.spring import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ExperimentalMaterialApi
@ -49,7 +48,7 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.lifecycle.flowWithLifecycle import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.navigation.plusAssign import androidx.navigation.plusAssign
import androidx.window.layout.FoldingFeature import androidx.window.layout.FoldingFeature
@ -114,7 +113,7 @@ val LocalNotificationCountFlow =
val LocalDevicePosture = val LocalDevicePosture =
staticCompositionLocalOf<State<DevicePosture>> { throw IllegalStateException("not allowed here!") } staticCompositionLocalOf<State<DevicePosture>> { throw IllegalStateException("not allowed here!") }
val LocalNavController = val LocalNavController =
staticCompositionLocalOf<NavController> { throw IllegalStateException("not allowed here!") } staticCompositionLocalOf<NavHostController> { throw IllegalStateException("not allowed here!") }
val LocalDestination = compositionLocalOf<DestinationSpec<*>?> { null } val LocalDestination = compositionLocalOf<DestinationSpec<*>?> { null }
@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterialNavigationApi::class) @OptIn(ExperimentalMaterialApi::class, ExperimentalMaterialNavigationApi::class)
@ -276,94 +275,44 @@ class MainActivityV2 : BaseComposeActivity() {
PickMediasRequest(it.id, it.maxCount, it.mediaType) PickMediasRequest(it.id, it.maxCount, it.mediaType)
) )
} }
CompositionLocalProvider( TiebaLiteLocalProvider {
LocalNotificationCountFlow provides notificationCountFlow, TranslucentThemeBackground {
LocalDevicePosture provides devicePostureFlow.collectAsState(), val navController = rememberNavController()
) { val engine = TiebaNavHostDefaults.rememberNavHostEngine()
Box { val navigator = TiebaNavHostDefaults.rememberBottomSheetNavigator()
TranslucentThemeBackground() val currentDestination by navController.currentDestinationAsState()
Surface( navController.navigatorProvider += navigator
color = ExtendedTheme.colors.background
LaunchedEffect(currentDestination) {
val curDest = currentDestination
if (curDest != null) {
Analytics.trackEvent(
"PageChanged",
mapOf(
"page" to curDest.route,
)
)
}
}
CompositionLocalProvider(
LocalNavController provides navController,
LocalDestination provides currentDestination,
) { ) {
val animationSpec = remember { ModalBottomSheetLayout(
spring( bottomSheetNavigator = navigator,
stiffness = Spring.StiffnessMediumLow, sheetShape = RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp),
visibilityThreshold = IntOffset.VisibilityThreshold sheetBackgroundColor = ExtendedTheme.colors.windowBackground
)
}
val engine = rememberAnimatedNavHostEngine(
navHostContentAlignment = Alignment.TopStart,
rootDefaultAnimations = RootNavGraphDefaultAnimations(
enterTransition = {
slideIntoContainer(
AnimatedContentTransitionScope.SlideDirection.Start,
animationSpec = animationSpec,
initialOffset = { it }
)
},
exitTransition = {
slideOutOfContainer(
AnimatedContentTransitionScope.SlideDirection.End,
animationSpec = animationSpec,
targetOffset = { -it }
)
},
popEnterTransition = {
slideIntoContainer(
AnimatedContentTransitionScope.SlideDirection.Start,
animationSpec = animationSpec,
initialOffset = { -it }
)
},
popExitTransition = {
slideOutOfContainer(
AnimatedContentTransitionScope.SlideDirection.End,
animationSpec = animationSpec,
targetOffset = { it }
)
},
),
)
val navController = rememberNavController()
val bottomSheetNavigator =
rememberBottomSheetNavigator(
animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
skipHalfExpanded = true
)
navController.navigatorProvider += bottomSheetNavigator
val currentDestination by navController.currentDestinationAsState()
LaunchedEffect(currentDestination) {
val curDest = currentDestination
if (curDest != null) {
Analytics.trackEvent(
"PageChanged",
mapOf(
"page" to curDest.route,
)
)
}
}
CompositionLocalProvider(
LocalNavController provides navController,
LocalDestination provides currentDestination
) { ) {
ModalBottomSheetLayout( DestinationsNavHost(
bottomSheetNavigator = bottomSheetNavigator, navController = navController,
sheetShape = RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp), navGraph = NavGraphs.root,
sheetBackgroundColor = ExtendedTheme.colors.windowBackground, engine = engine,
) { dependenciesContainerBuilder = {
DestinationsNavHost( dependency(MainPageDestination) { this@MainActivityV2 }
navController = navController, }
navGraph = NavGraphs.root, )
engine = engine,
dependenciesContainerBuilder = {
dependency(MainPageDestination) { this@MainActivityV2 }
}
)
}
} }
} }
} }
@ -371,19 +320,38 @@ class MainActivityV2 : BaseComposeActivity() {
} }
@Composable @Composable
private fun TranslucentThemeBackground() { private fun TranslucentThemeBackground(
if (ThemeUtil.isTranslucentTheme(ExtendedTheme.colors.theme)) { modifier: Modifier = Modifier,
val backgroundPath by rememberPreferenceAsMutableState( content: @Composable () -> Unit,
key = stringPreferencesKey("translucent_theme_background_path"), ) {
defaultValue = "" Surface(
) color = ExtendedTheme.colors.background,
val backgroundUri by remember { derivedStateOf { newFileUri(backgroundPath) } } modifier = modifier
AsyncImage( ) {
imageUri = backgroundUri, if (ThemeUtil.isTranslucentTheme(ExtendedTheme.colors.theme)) {
contentDescription = null, val backgroundPath by rememberPreferenceAsMutableState(
modifier = Modifier.fillMaxSize(), key = stringPreferencesKey("translucent_theme_background_path"),
contentScale = ContentScale.Crop defaultValue = ""
) )
val backgroundUri by remember { derivedStateOf { newFileUri(backgroundPath) } }
AsyncImage(
imageUri = backgroundUri,
contentDescription = null,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop
)
}
content()
}
}
@Composable
fun TiebaLiteLocalProvider(content: @Composable () -> Unit) {
CompositionLocalProvider(
LocalNotificationCountFlow provides notificationCountFlow,
LocalDevicePosture provides devicePostureFlow.collectAsState(),
) {
content()
} }
} }
@ -401,4 +369,54 @@ class MainActivityV2 : BaseComposeActivity() {
} }
} }
} }
}
private object TiebaNavHostDefaults {
private val AnimationSpec = spring(
stiffness = Spring.StiffnessMediumLow,
visibilityThreshold = IntOffset.VisibilityThreshold
)
@Composable
@OptIn(ExperimentalMaterialNavigationApi::class, ExperimentalAnimationApi::class)
fun rememberNavHostEngine() = rememberAnimatedNavHostEngine(
navHostContentAlignment = Alignment.TopStart,
rootDefaultAnimations = RootNavGraphDefaultAnimations(
enterTransition = {
slideIntoContainer(
AnimatedContentTransitionScope.SlideDirection.Start,
animationSpec = AnimationSpec,
initialOffset = { it }
)
},
exitTransition = {
slideOutOfContainer(
AnimatedContentTransitionScope.SlideDirection.End,
animationSpec = AnimationSpec,
targetOffset = { -it }
)
},
popEnterTransition = {
slideIntoContainer(
AnimatedContentTransitionScope.SlideDirection.Start,
animationSpec = AnimationSpec,
initialOffset = { -it }
)
},
popExitTransition = {
slideOutOfContainer(
AnimatedContentTransitionScope.SlideDirection.End,
animationSpec = AnimationSpec,
targetOffset = { it }
)
},
),
)
@OptIn(ExperimentalMaterialNavigationApi::class)
@Composable
fun rememberBottomSheetNavigator(): BottomSheetNavigator = rememberBottomSheetNavigator(
animationSpec = spring(stiffness = Spring.StiffnessMediumLow),
skipHalfExpanded = true
)
} }

View File

@ -15,7 +15,7 @@ buildscript {
booster_version = '4.16.2' booster_version = '4.16.2'
lottie_version = '6.1.0' lottie_version = '6.1.0'
debug = gradle.startParameter.taskNames.any { debug = gradle.startParameter.taskNames.any {
it.contains('debug') || it.contains('Debug') it.containsIgnoreCase('debug')
} }
} }
repositories { repositories {