我正在使用 Jetpack compose,并在用户单击通知时触发 jetpack compose 深层链接。 这就是我在收到通知并且用户在应用程序中时创建通知的方式:
class NotificationService : FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) {
message.notification?.let { notification ->
val builder = NotificationCompat.Builder(this, "notification")
.setSmallIcon(R.mipmap.ic_logo)
.setContentTitle(notification.title)
.setContentText(notification.body)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_DEFAULT).apply {
message.data["category"]?.let { category ->
this.setContentIntent(notificationDeepLinkHandler(category = category))
}
}
with(NotificationManagerCompat.from(this)) {
notify(1, builder.build())
}
}
}
}
一切正常,但它会导致 MainActivity 重新创建,这很糟糕,因为这是我的 MainActivity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
intent.extras?.getString("category")?.let {
notificationDeepLinkHandler(it)
}
createNotificationChannel()
setContent {
MyTheme {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = viewModel.destination) {
landingNavBuilder(navController = navController)
appNavBuilder()
AuthenticationHandler(
navController = navController,
isUserAuthenticated = viewModel.isUserAuthenticated
)
SplashScreen()
}
}
}
}
如前所述,我有一个可组合的
SplashScreen()
,每当用户打开应用程序时就会出现,并会在 2 秒后消失。它有自己的视图模型并且仅显示一次。但由于启动新意图会导致视图模型被破坏,因此它会再次出现。我该如何解决?
将标志设置为“SingleInstance”、“SingleTask”等方法没有帮助。
<activity
android:launchMode="singleTask"
android:name=".main.presentation.activity.MainActivity"
android:exported="true"
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<data android:host="deeplink" android:scheme="myapp" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.intent.action.VIEW"/>
</intent-filter>
</activity>
我尝试通过设置活动启动模式标志来改变行为,但没有帮助。
为了防止由于深层链接而重新创建 MainActivity 时 SplashScreen 再次出现,您可以在 SplashScreen 可组合项中使用记住功能。 此函数允许您存储一个在重新组合时会被记住的值,因此 SplashScreen 只会显示一次。 首先,您需要创建一个记住值来存储 SplashScreen 是否已显示的状态。 您可以通过在 MainActivity 的 onCreate 方法中的 setContent 块之前添加以下代码来完成此操作:
kotlin
val splashScreenShown = remember { mutableStateOf(false) }
接下来,您需要修改 SplashScreen 可组合项以接受 MutableState 参数,该参数将用于在显示 SplashScreen 后更新splashScreenShown 的状态:
kotlin
@Composable
fun SplashScreen(splashScreenShown: MutableState<Boolean>) {
// SplashScreen implementation
// After the SplashScreen has been displayed, update the state:
splashScreenShown.value = true
}
最后,需要根据splashScreenShown的值有条件地显示SplashScreen。您可以通过在 setContent 块内添加 if 语句来做到这一点:
kotlin
setContent {
MyTheme {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = viewModel.destination) {
landingNavBuilder(navController = navController)
appNavBuilder()
AuthenticationHandler(
navController = navController,
isUserAuthenticated = viewModel.isUserAuthenticated
)
if (!splashScreenShown.value) {
SplashScreen(splashScreenShown)
}
}
}
}
通过这些更改,即使 MainActivity 由于深度链接而重新创建,SplashScreen 也只会显示一次。