rememberLauncherForActivityResult 抛出 Launcher has not been initialized in Jetpack Compose
rememberLauncherForActivityResult throws Launcher has not been initialized in Jetpack Compose
尝试调用 Firebase Auth UI 时,使用以下代码,编译器会抛出 java.lang.IllegalStateException:启动器尚未初始化。不确定,为什么启动器没有初始化
@Composable
internal fun ProfileUI(profileViewModel: ProfileViewModel) {
val loginLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result != null) {
//do something
}
}
if (profileViewModel.isAnonymousUser) {
loginLauncher.launch(profileViewModel.buildLoginIntent())
} else {
}
}
override fun buildLoginIntent(): Intent {
val authUILayout = AuthMethodPickerLayout.Builder(R.layout.auth_ui)
.setGoogleButtonId(R.id.btn_gmail)
.setEmailButtonId(R.id.btn_email)
.build()
return AuthUI.getInstance().createSignInIntentBuilder()
.setIsSmartLockEnabled(!BuildConfig.DEBUG)
.setAvailableProviders(
listOf(
AuthUI.IdpConfig.EmailBuilder().build(),
AuthUI.IdpConfig.GoogleBuilder().build()
)
)
.enableAnonymousUsersAutoUpgrade()
.setLogo(R.mipmap.ic_launcher)
.setAuthMethodPickerLayout(authUILayout)
.build()
}
java.lang.IllegalStateException: Launcher has not been initialized
at androidx.activity.compose.ActivityResultLauncherHolder.launch(ActivityResultRegistry.kt:153)
at androidx.activity.compose.ManagedActivityResultLauncher.launch(ActivityResultRegistry.kt:142)
at androidx.activity.result.ActivityResultLauncher.launch(ActivityResultLauncher.java:47)
at com.madhu.locationbuddy.profile.ProfileUIKt.ProfileUI(ProfileUI.kt:37)
at com.madhu.locationbuddy.profile.ProfileUIKt.ProfileUI(ProfileUI.kt:15)
关于如何解决这个问题有什么想法吗?
根据 Side-effects in Compose documentation:
Composables should be side-effect free.
Key Term: A side-effect is a change to the state of the app that happens outside the scope of a composable function.
启动另一个 activity,例如调用 launch
,绝对是一种副作用,因此绝不能作为组合本身的一部分来完成。
相反,您应该将启动调用放在其中一个 Effect API 中,例如 SideEffect
(如果您希望它在每个组合上都 运行)或 LaunchedEffect
(当输入改变时只有 运行s - 如果 profileViewModel.isAnonymousUser
是由 mutableStateOf()
驱动的,那将是合适的。
因此您的代码可以更改为:
internal fun ProfileUI(profileViewModel: ProfileViewModel) {
val loginLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result != null) {
//do something
}
}
if (profileViewModel.isAnonymousUser) {
SideEffect {
loginLauncher.launch(profileViewModel.buildLoginIntent())
}
} else {
// Output your UI, etc.
}
}
尝试调用 Firebase Auth UI 时,使用以下代码,编译器会抛出 java.lang.IllegalStateException:启动器尚未初始化。不确定,为什么启动器没有初始化
@Composable
internal fun ProfileUI(profileViewModel: ProfileViewModel) {
val loginLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result != null) {
//do something
}
}
if (profileViewModel.isAnonymousUser) {
loginLauncher.launch(profileViewModel.buildLoginIntent())
} else {
}
}
override fun buildLoginIntent(): Intent {
val authUILayout = AuthMethodPickerLayout.Builder(R.layout.auth_ui)
.setGoogleButtonId(R.id.btn_gmail)
.setEmailButtonId(R.id.btn_email)
.build()
return AuthUI.getInstance().createSignInIntentBuilder()
.setIsSmartLockEnabled(!BuildConfig.DEBUG)
.setAvailableProviders(
listOf(
AuthUI.IdpConfig.EmailBuilder().build(),
AuthUI.IdpConfig.GoogleBuilder().build()
)
)
.enableAnonymousUsersAutoUpgrade()
.setLogo(R.mipmap.ic_launcher)
.setAuthMethodPickerLayout(authUILayout)
.build()
}
java.lang.IllegalStateException: Launcher has not been initialized
at androidx.activity.compose.ActivityResultLauncherHolder.launch(ActivityResultRegistry.kt:153)
at androidx.activity.compose.ManagedActivityResultLauncher.launch(ActivityResultRegistry.kt:142)
at androidx.activity.result.ActivityResultLauncher.launch(ActivityResultLauncher.java:47)
at com.madhu.locationbuddy.profile.ProfileUIKt.ProfileUI(ProfileUI.kt:37)
at com.madhu.locationbuddy.profile.ProfileUIKt.ProfileUI(ProfileUI.kt:15)
关于如何解决这个问题有什么想法吗?
根据 Side-effects in Compose documentation:
Composables should be side-effect free.
Key Term: A side-effect is a change to the state of the app that happens outside the scope of a composable function.
启动另一个 activity,例如调用 launch
,绝对是一种副作用,因此绝不能作为组合本身的一部分来完成。
相反,您应该将启动调用放在其中一个 Effect API 中,例如 SideEffect
(如果您希望它在每个组合上都 运行)或 LaunchedEffect
(当输入改变时只有 运行s - 如果 profileViewModel.isAnonymousUser
是由 mutableStateOf()
驱动的,那将是合适的。
因此您的代码可以更改为:
internal fun ProfileUI(profileViewModel: ProfileViewModel) {
val loginLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result != null) {
//do something
}
}
if (profileViewModel.isAnonymousUser) {
SideEffect {
loginLauncher.launch(profileViewModel.buildLoginIntent())
}
} else {
// Output your UI, etc.
}
}