Fix recomposition causing repeat get of extras

This commit is contained in:
Ash 2022-03-28 18:12:21 +08:00
parent a1ceb9a489
commit 67b033f1ec
4 changed files with 137 additions and 122 deletions

View File

@ -14,7 +14,9 @@ class MainActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
HomeEntry()
HomeEntry(intent.extras).also {
intent.replaceExtras(null)
}
}
}
}

View File

@ -1,5 +1,6 @@
package me.ash.reader.ui.page.common
import android.os.Bundle
import androidx.compose.animation.*
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
@ -27,7 +28,9 @@ import me.ash.reader.ui.theme.AppTheme
@OptIn(ExperimentalAnimationApi::class, androidx.compose.material.ExperimentalMaterialApi::class)
@Composable
fun HomeEntry() {
fun HomeEntry(
extras: Bundle? = null,
) {
val navController = rememberAnimatedNavController()
AppTheme {
@ -40,100 +43,100 @@ fun HomeEntry() {
Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) {
Row(
modifier = Modifier
.weight(1f)
.statusBarsPadding()
.weight(1f)
.statusBarsPadding()
) {
AnimatedNavHost(
navController = navController,
startDestination = RouteName.HOME,
) {
AnimatedNavHost(
navController = navController,
startDestination = RouteName.HOME,
composable(
route = RouteName.HOME,
enterTransition = {
slideInHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
initialOffsetX = { -it }
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
},
exitTransition = {
slideOutHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
targetOffsetX = { it }
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
},
popEnterTransition = {
slideInHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
initialOffsetX = { -it }
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
},
popExitTransition = {
slideOutHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
targetOffsetX = { it }
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
},
) {
composable(
route = RouteName.HOME,
enterTransition = {
slideInHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
initialOffsetX = { -it }
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
},
exitTransition = {
slideOutHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
targetOffsetX = { it }
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
},
popEnterTransition = {
slideInHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
initialOffsetX = { -it }
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
},
popExitTransition = {
slideOutHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
targetOffsetX = { it }
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
},
) {
HomePage(navController)
}
composable(
route = RouteName.SETTINGS,
enterTransition = {
slideInHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
initialOffsetX = { -it }
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
},
exitTransition = {
slideOutHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
targetOffsetX = { -it }
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
},
popEnterTransition = {
slideInHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
initialOffsetX = { -it }
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
},
popExitTransition = {
slideOutHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
targetOffsetX = { -it }
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
},
) {
SettingsPage(navController)
}
HomePage(navController, extras?.get(ExtraName.ARTICLE_ID))
}
composable(
route = RouteName.SETTINGS,
enterTransition = {
slideInHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
initialOffsetX = { -it }
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
},
exitTransition = {
slideOutHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
targetOffsetX = { -it }
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
},
popEnterTransition = {
slideInHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
initialOffsetX = { -it }
) + fadeIn(animationSpec = tween(220, delayMillis = 90))
},
popExitTransition = {
slideOutHorizontally(
animationSpec = spring(
stiffness = Spring.StiffnessLow,
dampingRatio = Spring.DampingRatioNoBouncy
),
targetOffsetX = { -it }
) + fadeOut(animationSpec = tween(220, delayMillis = 90))
},
) {
SettingsPage(navController)
}
}
Spacer(
modifier = Modifier
.navigationBarsHeight()
}
Spacer(
modifier = Modifier
.navigationBarsHeight()
.fillMaxWidth()
)
}

View File

@ -9,15 +9,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.google.accompanist.pager.ExperimentalPagerApi
import kotlinx.coroutines.launch
import me.ash.reader.ui.extension.collectAsStateValue
import me.ash.reader.ui.extension.findActivity
import me.ash.reader.ui.page.common.ExtraName
import me.ash.reader.ui.page.home.drawer.feed.FeedOptionDrawer
import me.ash.reader.ui.page.home.drawer.feed.FeedOptionViewAction
import me.ash.reader.ui.page.home.drawer.feed.FeedOptionViewModel
@ -32,41 +28,17 @@ import me.ash.reader.ui.widget.ViewPager
@Composable
fun HomePage(
navController: NavHostController,
extrasArticleId: Any? = null,
viewModel: HomeViewModel = hiltViewModel(),
readViewModel: ReadViewModel = hiltViewModel(),
feedOptionViewModel: FeedOptionViewModel = hiltViewModel(),
) {
val context = LocalContext.current
val viewState = viewModel.viewState.collectAsStateValue()
val filterState = viewModel.filterState.collectAsStateValue()
val readState = readViewModel.viewState.collectAsStateValue()
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
context.findActivity()?.let { activity ->
activity.intent?.let { intent ->
intent.extras?.get(ExtraName.ARTICLE_ID)?.let {
readViewModel.dispatch(ReadViewAction.ScrollToItem(2))
scope.launch {
val article = readViewModel
.rssRepository.get()
.findArticleById(it.toString()) ?: return@launch
readViewModel.dispatch(ReadViewAction.InitData(article))
if (article.feed.isFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
else readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
viewModel.dispatch(
HomeViewAction.ScrollToPage(
scope = scope,
targetPage = 2,
)
)
}
}
intent.extras?.remove(ExtraName.ARTICLE_ID)
}
}
}
OpenArticleByExtras(extrasArticleId)
BackHandler(true) {
val currentPage = viewState.pagerState.currentPage

View File

@ -0,0 +1,38 @@
package me.ash.reader.ui.page.home
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.hilt.navigation.compose.hiltViewModel
import kotlinx.coroutines.launch
import me.ash.reader.ui.page.home.read.ReadViewAction
import me.ash.reader.ui.page.home.read.ReadViewModel
@Composable
fun OpenArticleByExtras(
extrasArticleId: Any? = null,
homeViewModel: HomeViewModel = hiltViewModel(),
readViewModel: ReadViewModel = hiltViewModel(),
) {
val scope = rememberCoroutineScope()
LaunchedEffect(extrasArticleId) {
extrasArticleId?.let {
readViewModel.dispatch(ReadViewAction.ScrollToItem(2))
this.launch {
val article = readViewModel
.rssRepository.get()
.findArticleById(it.toString()) ?: return@launch
readViewModel.dispatch(ReadViewAction.InitData(article))
if (article.feed.isFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
else readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
homeViewModel.dispatch(
HomeViewAction.ScrollToPage(
scope = scope,
targetPage = 2,
)
)
}
}
}
}