Jetpack Compose+;androidx.compose.runtime.SlotTableKt.groupSize(SlotTable.kt:2558)上的Firebase崩溃java.lang.ArrayIndexOutOfBoundsException

Jetpack Compose+;androidx.compose.runtime.SlotTableKt.groupSize(SlotTable.kt:2558)上的Firebase崩溃java.lang.ArrayIndexOutOfBoundsException,android,firebase,kotlin,google-cloud-firestore,android-jetpack-compose,Android,Firebase,Kotlin,Google Cloud Firestore,Android Jetpack Compose,我正在使用firbase firestore实时数据库开发一个应用程序。 一旦用户首次登录,应用程序将检查用户是否有用户名。如果没有,它将显示一个弹出窗口,允许更改用户名。用户还可以通过抽屉菜单更改用户名,该菜单也将显示相同的弹出窗口 这是我的viewmodel的外观: class MainViewModel : ViewModel() { private val _user = FirebaseAuth.getInstance().currentUser private val

我正在使用firbase firestore实时数据库开发一个应用程序。 一旦用户首次登录,应用程序将检查用户是否有用户名。如果没有,它将显示一个弹出窗口,允许更改用户名。用户还可以通过抽屉菜单更改用户名,该菜单也将显示相同的弹出窗口

这是我的viewmodel的外观:

class MainViewModel : ViewModel() {
    private val _user = FirebaseAuth.getInstance().currentUser
    private val _isLoggedIn = MutableLiveData(FirebaseAuth.getInstance().currentUser != null)
    val profile = UserProfile(_user.uid)

    var isLoaded: LiveData<Boolean> = profile.isLoaded
    var isLoggedIn: LiveData<Boolean> = _isLoggedIn

    init {
        getInstance().addAuthStateListener() {
            _isLoggedIn.value = it.currentUser != null
        }
    }

    fun updateUsername(username: String) {
        profile.updateUsername(username)
    }

    fun logOut(){
        FirebaseAuth.getInstance().signOut()
    }

}
最后,我的change用户名组合如下所示:

class UserProfile(private val userId: String) {

    private val _isLoaded = MutableLiveData(false)
    private val _username = MutableLiveData("")

    var isLoaded: LiveData<Boolean> = _isLoaded
    var username: LiveData<String> = _username

    init {
        if (userId != "") {
            Firebase.firestore.collection("Users").document(userId)
                .addSnapshotListener { snapshot, e ->
                    if (e != null)
                        return@addSnapshotListener
                    if (snapshot != null) {
                        if (snapshot.exists()) {
                            snapshot.getString("username")?.let { setUsername(it) }
                            if (_isLoaded.value == false)
                                _isLoaded.value = true
                        } else {
                            val data = hashMapOf("username" to "")
                            FirebaseFirestore.getInstance().collection("Users").document("")
                                .set(data)
                        }
                    }
                }
        }
    }

    private fun setUsername(newUsername: String) {
        _username.value = newUsername
    }

    fun updateUsername(newUsername: String) {
        if (userId != "") {
            val data = hashMapOf("username" to newUsername)
            FirebaseFirestore.getInstance().collection("Users").document(userId)
                .set(data, SetOptions.merge())
        }
    }
}
fun Main(mainViewmodel: MainViewModel = viewModel(), navHostController: NavHostController) {
    var fabShape = CircleShape
    val state = rememberScaffoldState()
    val scope = rememberCoroutineScope()
    val isLoggedIn: Boolean by mainViewmodel.isLoggedIn.observeAsState(true)
    val isLoaded: Boolean by mainViewmodel.isLoaded.observeAsState(false)
    val username: String by mainViewmodel.profile.username.observeAsState("")
    var showUsernameChange: Boolean by remember (username){ mutableStateOf(false)}
    if (!isLoggedIn)
        navHostController.navigate(Screen.Login.route)
    Scaffold(
        scaffoldState = state,
        topBar = {
            TopAppBar(
                title = { Text(text = "AppName") },
                navigationIcon = {
                    IconButton(onClick = {
                        if (state.drawerState.isClosed) scope.launch { state.drawerState.open() }
                        else scope.launch { state.drawerState.close() }
                    }) {
                        Icon(Icons.Filled.AccountCircle, null)
                    }
                }

            )
        },
        bottomBar = {
            BottomAppBar(cutoutShape = fabShape) {
                BottomNavigationItem(
                    selected = true,
                    onClick = { /*TODO*/ },
                    icon = { Icon(Icons.Filled.Home, null) })
                BottomNavigationItem(
                    selected = false,
                    onClick = { /*TODO*/ },
                    icon = { Icon(Icons.Filled.Favorite, null) })
                BottomNavigationItem(
                    selected = false,
                    onClick = { /*TODO*/ },
                    icon = { Icon(Icons.Filled.Search, null) })
                BottomNavigationItem(
                    selected = false,
                    onClick = { /*TODO*/ },
                    icon = { Icon(Icons.Filled.Settings, null) })
            }
        },
        drawerShape = RoundedCornerShape(
            topStart = 10.dp,
            topEnd = 10.dp,
            bottomStart = 10.dp,
            bottomEnd = 10.dp,
        ),
        drawerContent = {
            Drawer(username = username, onLogoutClick = {mainViewmodel.logOut()}, onUsernameChangeClick = {
                showUsernameChange = true
                scope.launch { state.drawerState.close() }
            })
        },
        drawerGesturesEnabled = true,
        isFloatingActionButtonDocked = true,
        floatingActionButtonPosition = FabPosition.Center,
        floatingActionButton = {
            FloatingActionButton(
                onClick = { /*TODO*/ },
                shape = fabShape,
                content = { Icon(Icons.Filled.Add, null) })
        }
    ) {
        if (isLoaded) {
            content(mainViewmodel = mainViewmodel)
            val hasUsername: Boolean by remember(username) { mutableStateOf(username.isNotEmpty())}
            if (!hasUsername || showUsernameChange) {
                var cacheUsername: String by remember { mutableStateOf(username) }
                    changeUsername(
                        cacheUsername,
                        onNameChange = { cacheUsername = it },
                        onDismiss = {if(showUsernameChange){
                            showUsernameChange = false
                        } },
                        onDoneClick = {
                            mainViewmodel.updateUsername(cacheUsername)
                        })
                }
        } else {
            loading()
        }

    }
}
fun changeUsername(username: String, onNameChange : (String) -> Unit, onDoneClick : () -> Unit, onDismiss: () -> Unit){
    val error : Boolean = username.isNullOrEmpty() || username.length > 64 || username.length < 4
    Dialog(onDismissRequest = { onDismiss() }) {
        Card() {
            Column(modifier = Modifier.padding(4.dp)) {
                Text(text = "Update Username", modifier = Modifier.padding(4.dp), style = MaterialTheme.typography.subtitle2)
                TextField(value = username,
                    onValueChange = { onNameChange(it) },
                    modifier = Modifier.padding(4.dp),
                    isError = error,
                    placeholder = { Text("Username") })
                TextButton(
                    onClick = { onDoneClick() }, modifier = Modifier
                        .padding(4.dp)
                        .align(Alignment.End),
                    enabled = !error
                ) {
                    Text("Done")
                }
            }

        }

    }

}

这是怎么回事?我们如何修复它?

看起来像这样。看起来修复程序已经实现,有望在Beta 2中发布!你认为它与对话有关吗?是的,这就是它的样子。确认。删除对话框,工作正常。您认为我应该将此报告为一个问题吗?还有一个问题的代码与您的()类似,但它被标记为与我之前链接的问题重复。鉴于stacktrace完全相同,因此值得验证该问题是否在最新的Compose快照上得到了解决。您可以按照androidx.dev上的说明将其包括在内。如果这不能解决您的问题,请提交另一个问题。
 java.lang.ArrayIndexOutOfBoundsException: length=5120; index=-2
        at androidx.compose.runtime.SlotTableKt.groupSize(SlotTable.kt:2558)
        at androidx.compose.runtime.SlotTableKt.access$groupSize(SlotTable.kt:1)
        at androidx.compose.runtime.SlotReader.groupSize(SlotTable.kt:596)
        at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2215)
        at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2499)
        at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:2625)
        at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:406)
        at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:724)
        at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:100)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:437)
        at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:411)
        at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
        at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:112)
        at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:43)
        at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:72)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:964)
        at android.view.Choreographer.doCallbacks(Choreographer.java:790)
        at android.view.Choreographer.doFrame(Choreographer.java:721)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:951)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)