Kotlin多平台Android应用在Activity进入后台时崩溃

agxfikkp  于 11个月前  发布在  Android
关注(0)|答案(1)|浏览(122)

我已经开发了一个KMP项目,成功地建立在iOS和Android.我注意到,我无法后台的Android应用程序,并恢复活动.它将始终重新创建活动,并失去所有用户输入之前完成.
看起来主要的问题来自一个可序列化对象的写异常。我只是不确定从这里开始,我应该在这里分享多少代码(或链接到整个仓库),让经历过类似问题的人重现这个问题。任何建议都很感激。
Android Studio Giraffe| 2022.3.1 Patch 2 VM:OpenJDK 64-Bit Server VM by JetBrains s.r.o. macOS 13.6.1
Kotlin多平台版本1.9.10,Gradle插件8.1.0

FATAL EXCEPTION: main
Process: org.haspohr.cmr, PID: 3145
android.os.BadParcelableException: Parcelable encountered IOException writing serializable object (name = org.haspohr.cmr12.screens.StartScreen)
    at android.os.Parcel.writeSerializable(Parcel.java:2797)
    at android.os.Parcel.writeValue(Parcel.java:2563)
    at android.os.Parcel.writeValue(Parcel.java:2362)
    at android.os.Parcel.writeList(Parcel.java:1415)
    at android.os.Parcel.writeValue(Parcel.java:2506)
    at android.os.Parcel.writeValue(Parcel.java:2362)
    at android.os.Parcel.writeList(Parcel.java:1415)
    at android.os.Parcel.writeValue(Parcel.java:2506)
    at android.os.Parcel.writeValue(Parcel.java:2362)
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:1298)
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1843)
    at android.os.Bundle.writeToParcel(Bundle.java:1389)
    at android.os.Parcel.writeBundle(Parcel.java:1367)
    at android.os.Parcel.writeValue(Parcel.java:2479)
    at android.os.Parcel.writeValue(Parcel.java:2369)
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:1298)
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1843)
    at android.os.Bundle.writeToParcel(Bundle.java:1389)
    at android.os.Parcel.writeBundle(Parcel.java:1367)
    at android.os.Parcel.writeValue(Parcel.java:2479)
    at android.os.Parcel.writeValue(Parcel.java:2369)
    at android.os.BaseBundle.dumpStats(BaseBundle.java:1917)
    at android.os.BaseBundle.dumpStats(BaseBundle.java:1954)
    at android.app.servertransaction.PendingTransactionActions$StopInfo.collectBundleStates(PendingTransactionActions.java:123)
    at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:139)
    at android.os.Handler.handleCallback(Handler.java:958)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:294)
    at android.app.ActivityThread.main(ActivityThread.java:8177)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by: java.io.NotSerializableException: org.haspohr.cmr12.GameViewModel
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1620)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1581)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1490)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354)
    at android.os.Parcel.writeSerializable(Parcel.java:2792)
    at android.os.Parcel.writeValue(Parcel.java:2563) 
    at android.os.Parcel.writeValue(Parcel.java:2362) 
    at android.os.Parcel.writeList(Parcel.java:1415) 
    at android.os.Parcel.writeValue(Parcel.java:2506) 
    at android.os.Parcel.writeValue(Parcel.java:2362) 
    at android.os.Parcel.writeList(Parcel.java:1415) 
    at android.os.Parcel.writeValue(Parcel.java:2506) 
    at android.os.Parcel.writeValue(Parcel.java:2362) 
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:1298) 
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1843) 
    at android.os.Bundle.writeToParcel(Bundle.java:1389) 
    at android.os.Parcel.writeBundle(Parcel.java:1367) 
    at android.os.Parcel.writeValue(Parcel.java:2479) 
    at android.os.Parcel.writeValue(Parcel.java:2369) 
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:1298) 
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1843) 
    at android.os.Bundle.writeToParcel(Bundle.java:1389) 
    at android.os.Parcel.writeBundle(Parcel.java:1367) 
    at android.os.Parcel.writeValue(Parcel.java:2479) 
    at android.os.Parcel.writeValue(Parcel.java:2369) 
    at android.os.BaseBundle.dumpStats(BaseBundle.java:1917) 
    at android.os.BaseBundle.dumpStats(BaseBundle.java:1954) 
    at android.app.servertransaction.PendingTransactionActions$StopInfo.collectBundleStates(PendingTransactionActions.java:123) 
    at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:139) 
    at android.os.Handler.handleCallback(Handler.java:958) 
    at android.os.Handler.dispatchMessage(Handler.java:99) 
    at android.os.Looper.loopOnce(Looper.java:205) 
    at android.os.Looper.loop(Looper.java:294) 
    at android.app.ActivityThread.main(ActivityThread.java:8177) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971) 

字符串
当我通过在模拟器中按下退出键或在真实的设备上进入主后台来最小化应用程序时,它应该能够恢复活动。相反,应用程序将始终重新启动,丢失以前的输入。
下面是GameViewModel类的开始:

class GameViewModel{
    private val _uiState = MutableStateFlow(GameUiState())
    val uiState: StateFlow<GameUiState> = _uiState.asStateFlow()
    var focussed:Int=0
    init {
        updateBSA()
        updateECV()
    }
    fun reset()
    {
        _uiState.value=GameUiState()
        updateBSA()
        updateECV()
        accept()
        focussed=0
    }

    fun updateWeight(w: String) {
        _uiState.update { currentState -> currentState.copy(weightVal = if (w.isNotBlank()) w else "") }
        _uiState.update { currentState -> currentState.copy(bsaChanged = true) }
        updateBSA()
    }

    fun togglepapillary(i:Int) {
        _uiState.update { currentState -> currentState.copy(papillary = i==1)}
    }


当我将类声明更改为:

class GameViewModel: Serializable {


Serializable是带红色下划线的,建议:此类型有一个构造函数,因此必须在这里初始化。此类型是final类型,因此不能从其继承。

nimxete2

nimxete21#

您的GameViewModel类的问题源于这样一个事实,即它试图直接序列化,但它包含不可序列化的组件。这导致当Android系统尝试保存您的Activity状态时,NotSerializableException for GameViewModel

**1.独立状态处理:**创建一个独立的数据类,表示GameViewModel中可序列化的状态,我们称之为SerializableGameState

data class SerializableGameState(
    val weightVal: String,
    val bsaChanged: Boolean,
    val papillary: Boolean,
    // Other serializable properties
)

字符串

**2.使用Serializable State:**修改您的GameViewModel,以处理SerializableGameState的示例。

class GameViewModel {
    private val _uiState = MutableStateFlow(GameUiState())
    val uiState: StateFlow<GameUiState> = _uiState.asStateFlow()

    // Other existing functions...

    fun getSerializableState(): SerializableGameState {
        val currentState = _uiState.value
        return SerializableGameState(
            weightVal = currentState.weightVal,
            bsaChanged = currentState.bsaChanged,
            papillary = currentState.papillary
            // Other properties you want to serialize...
        )
    }

    fun restoreStateFromSerializable(serializableState: SerializableGameState) {
        _uiState.value = GameUiState(
            weightVal = serializableState.weightVal,
            bsaChanged = serializableState.bsaChanged,
            papillary = serializableState.papillary
            // Restore other properties...
        )
    }
}

**3. Activity中的序列化处理:**当您的Activity需要序列化时,使用getSerializableState()函数提取可序列化的状态并保存,在序列化过程中使用restoreStateFromSerializable()恢复状态。

这将可序列化的状态与不可序列化的组件分开,允许您保存和恢复状态,而无需尝试序列化整个GameViewModel。然后,您可以根据需要持久化SerializableGameState,可能在Activity的onSaveInstanceState()onRestoreInstanceState()方法中。

  • 这种方法使您能够处理重要状态的持久性,而无需尝试序列化不可序列化的组件,从而避免遇到异常。*

相关问题