class WalletGiftDetailLandingArgs(
private val savedStateHandle: SavedStateHandle,
) {
val giftRefId: String
get() = savedStateHandle[KEY_GIFT_REF_ID] ?: ""
val isFromRedemptionReminderNotification: Boolean
get() = savedStateHandle[KEY_IS_FROM_REDEMPTION_REMINDER_NOTIFICATION] ?: false
}
object WalletGiftDetailDestination : NavigableDestination(
route = "$ROUTE/{$KEY_GIFT_TYPE}/{$KEY_GIFT_REF_ID}/{$KEY_IS_FROM_REDEMPTION_REMINDER_NOTIFICATION}",
)
fun NavGraphBuilder.walletGiftDetailScreen(
giftRefId: String = "",
isFromRedemptionReminderNotification: Boolean,
onClickBack: () -> Unit,
onRemoveFromWalletSuccess: () -> Unit,
onRedirectToReceivedGiftsScreen: () -> Unit,
) {
composable(
route = WalletGiftDetailDestination.route,
arguments = listOf(
navArgument(KEY_GIFT_REF_ID) {
type = NavType.StringType
defaultValue = giftRefId
},
navArgument(KEY_IS_FROM_REDEMPTION_REMINDER_NOTIFICATION) {
type = NavType.BoolType
defaultValue = isFromRedemptionReminderNotification
}
)
) {
WalletGiftDetailScreenRoute(
onClickBack = onClickBack,
onRemoveFromWalletSuccess = onRemoveFromWalletSuccess,
onRedirectToReceivedGiftsScreen = onRedirectToReceivedGiftsScreen
)
}
}
在ViewModel中,我可以安全地从SavedStateHandle中检索值。
在新的类型安全导航中,我尝试了以下操作:
@Serializable
class WalletGiftDetailLandingArgs(
val giftRefId: String,
val isFromRedemptionReminderNotification: Boolean,
)
fun NavGraphBuilder.walletGiftDetailScreen(
giftRefId: String = "",
isFromRedemptionReminderNotification: Boolean,
onClickBack: () -> Unit,
onRemoveFromWalletSuccess: () -> Unit,
onRedirectToReceivedGiftsScreen: () -> Unit,
) {
composable<WalletGiftDetailLandingArgs> {
WalletGiftDetailScreenRoute(
onClickBack = onClickBack,
onRemoveFromWalletSuccess = onRemoveFromWalletSuccess,
onRedirectToReceivedGiftsScreen = onRedirectToReceivedGiftsScreen
)
}
}
如果我尝试通过将默认值直接传递到组合性来处理默认值,我会遇到另一个问题:屏幕重编组件。每个重组再次调用函数,这可能导致ViewModel重新运行逻辑(例如传递给它的获取或处理值)。这效率低下,可能导致意外副作用。有一种适当的方法来定义类型安全导航系统中的默认参数,以避免这些问题,或者是否有建议的解决方法?
任何指导都将不胜感激!
任何指导都将不胜感激!
我在代码中添加了评论,以更好地理解。让我知道您是否有任何疑问。
// Destination Route
@Serializable
data class WalletGiftDetailDestination(
// argument
val giftRefId: String = "", // default value
// argument
val isFromRedemptionReminderNotification: Boolean = false, // default value
)
fun NavGraphBuilder.walletGiftDetailScreen(
// don't pass arguments here
// giftRefId: String = "",
// isFromRedemptionReminderNotification: Boolean,
onClickBack: () -> Unit,
onRemoveFromWalletSuccess: () -> Unit,
onRedirectToReceivedGiftsScreen: () -> Unit,
) {
composable<WalletGiftDetailDestination> { backStackEntry ->
// get arguments from backStackEntry if you want to pass them to screen composable instead of getting them in viewModel
val destination: WalletGiftDetailDestination = backStackEntry.toRoute()
WalletGiftDetailScreenRoute(
giftRefId = destination.giftRefId,
isFromRedemptionReminderNotification = destination.isFromRedemptionReminderNotification,
onClickBack = onClickBack,
onRemoveFromWalletSuccess = onRemoveFromWalletSuccess,
onRedirectToReceivedGiftsScreen = onRedirectToReceivedGiftsScreen
)
}
}
/////////////////////////////////////////
// can be used to get arguments in viewModel but seems boilerplate code to me with type-safe navigation
class WalletGiftDetailLandingArgs(
private val savedStateHandle: SavedStateHandle,
) {
val giftRefId: String
get() = savedStateHandle.toRoute<WalletGiftDetailDestination>().giftRefId
val isFromRedemptionReminderNotification: Boolean
get() = savedStateHandle.toRoute<WalletGiftDetailDestination>().isFromRedemptionReminderNotification
}
class WalletGiftDetailViewModel(
savedStateHandle: SavedStateHandle,
) : ViewModel() {
// get arguments from savedStateHandle in viewModel using WalletGiftDetailLandingArgs helper class
private val args = WalletGiftDetailLandingArgs(savedStateHandle)
private val betterArgs = savedStateHandle.toRoute<WalletGiftDetailDestination>()
init {
println(args.giftRefId)
println(args.isFromRedemptionReminderNotification)
println(betterArgs.giftRefId)
println(betterArgs.isFromRedemptionReminderNotification)
}
}
/////////////////////////////////////////
navController.navigate(
WalletGiftDetailDestination(
// pass arguments here if needed otherwise default values will be used
)
)