Android – 使用可序列化回调的 DialogFragment 在片段销毁时崩溃

huangapple go评论59阅读模式
英文:

Android - DialogFragment With Serializable Callback Crashes on Fragment Destruction

问题

以下是你提供的内容的翻译:

我的片段中包含一个对话框片段,并且为了在对话框的按钮被点击时接收回调,我将一个可序列化的接口传递给它的参数。

问题是,每当对话框显示时,如果用户切换到 Android 主屏幕,应用程序就会崩溃。

注意:根据我的日志,销毁顺序从主片段开始,以对话框片段结束。

初始化对话框片段的代码:

Navigation.findNavController(binding.root).navigate(GameFragmentDirections.actionGameFragmentToPauseDialogFragment(
    object : PauseDialogFragment.ResumeGameListener {
        override fun onResume() {
            isGamePaused = false
            onStartGame(_screenSizePairXY)
        }
    }))

可序列化的回调接口:

interface ResumeGameListener : Serializable {
    fun onResume()
}

堆栈跟踪信息:

java.lang.RuntimeException: 在写入可序列化对象时遇到 Parcelable 遇到 IOException (名称 = ui.game.GameFragment$onGameOver$1)
    // 具体的堆栈跟踪信息...
Caused by: java.io.NotSerializableException: com.developerkurt.ghosky.ui.game.GameFragment
    // 具体的堆栈跟踪信息...

请注意,以上内容是你提供的信息的翻译。如果你还有其他需要帮助的地方,请随时告诉我。

英文:

My fragment has a dialog fragment and to receive a callback when the dialog's button is clicked, I pass a serializable interface to its arguments.

The problem is, whenever the dialog is displayed if the user switches to the android home screen, the app crashes.

NOTE: According to my logs, destruction order is starting from the main fragment and ending with the dialog fragment.
<br><br>

Code to init dialog fragment:

       Navigation.findNavController(binding.root).navigate(GameFragmentDirections.actionGameFragmentToPauseDialogFragment(
                object : PauseDialogFragment.ResumeGameListener
                {
                    override fun onResume()
                    {
                        isGamePaused = false
                        onStartGame(_screenSizePairXY)
                    }
                }))

<br><br>

Serializable Callback Interface:

interface ResumeGameListener : Serializable
{
    fun onResume()
}

<br><br>

StackTrace

java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = ui.game.GameFragment$onGameOver$1)
    at android.os.Parcel.writeSerializable(Parcel.java:1714)
    at android.os.Parcel.writeValue(Parcel.java:1662)
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:875)
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1579)
    at android.os.Bundle.writeToParcel(Bundle.java:1233)
    at android.os.Parcel.writeBundle(Parcel.java:915)
    at androidx.fragment.app.FragmentState.writeToParcel(FragmentState.java:125)
    at android.os.Parcel.writeTypedObject(Parcel.java:1516)
    at android.os.Parcel.writeTypedList(Parcel.java:1395)
    at android.os.Parcel.writeTypedList(Parcel.java:1380)
    at androidx.fragment.app.FragmentManagerState.writeToParcel(FragmentManagerState.java:51)
    at android.os.Parcel.writeParcelable(Parcel.java:1683)
    at android.os.Parcel.writeValue(Parcel.java:1589)
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:875)
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1579)
    at android.os.Bundle.writeToParcel(Bundle.java:1233)
    at android.os.Parcel.writeBundle(Parcel.java:915)
    at androidx.fragment.app.FragmentState.writeToParcel(FragmentState.java:127)
    at android.os.Parcel.writeTypedObject(Parcel.java:1516)
    at android.os.Parcel.writeTypedList(Parcel.java:1395)
    at android.os.Parcel.writeTypedList(Parcel.java:1380)
    at androidx.fragment.app.FragmentManagerState.writeToParcel(FragmentManagerState.java:51)
    at android.os.Parcel.writeParcelable(Parcel.java:1683)
    at android.os.Parcel.writeValue(Parcel.java:1589)
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:875)
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1579)
    at android.os.Bundle.writeToParcel(Bundle.java:1233)
    at android.app.IActivityManager$Stub$Proxy.activityStopped(IActivityManager.java:4008)
    at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:144)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6762)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
 Caused by: java.io.NotSerializableException: com.developerkurt.ghosky.ui.game.GameFragment
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1240)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1604)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1565)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1488)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1234)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:354)
    at android.os.Parcel.writeSerializable(Parcel.java:1709)
    at android.os.Parcel.writeValue(Parcel.java:1662)&#160;
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:875)&#160;
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1579)&#160;
    at android.os.Bundle.writeToParcel(Bundle.java:1233)&#160;
    at android.os.Parcel.writeBundle(Parcel.java:915)&#160;
    at androidx.fragment.app.FragmentState.writeToParcel(FragmentState.java:125)&#160;
    at android.os.Parcel.writeTypedObject(Parcel.java:1516)&#160;
    at android.os.Parcel.writeTypedList(Parcel.java:1395)&#160;
    at android.os.Parcel.writeTypedList(Parcel.java:1380)&#160;
    at androidx.fragment.app.FragmentManagerState.writeToParcel(FragmentManagerState.java:51)&#160;
    at android.os.Parcel.writeParcelable(Parcel.java:1683)&#160;
    at android.os.Parcel.writeValue(Parcel.java:1589)&#160;
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:875)&#160;
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1579)&#160;
    at android.os.Bundle.writeToParcel(Bundle.java:1233)&#160;
    at android.os.Parcel.writeBundle(Parcel.java:915)&#160;
    at androidx.fragment.app.FragmentState.writeToParcel(FragmentState.java:127)&#160;
    at android.os.Parcel.writeTypedObject(Parcel.java:1516)&#160;
    at android.os.Parcel.writeTypedList(Parcel.java:1395)&#160;
    at android.os.Parcel.writeTypedList(Parcel.java:1380)&#160;
    at androidx.fragment.app.FragmentManagerState.writeToParcel(FragmentManagerState.java:51)&#160;
    at android.os.Parcel.writeParcelable(Parcel.java:1683)&#160;
    at android.os.Parcel.writeValue(Parcel.java:1589)&#160;
    at android.os.Parcel.writeArrayMapInternal(Parcel.java:875)&#160;
    at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1579)&#160;
    at android.os.Bundle.writeToParcel(Bundle.java:1233)&#160;
    at android.app.IActivityManager$Stub$Proxy.activityStopped(IActivityManager.java:4008)&#160;
    at android.app.servertransaction.PendingTransactionActions$StopInfo.run(PendingTransactionActions.java:144)&#160;
    at android.os.Handler.handleCallback(Handler.java:873)&#160;
    at android.os.Handler.dispatchMessage(Handler.java:99)&#160;
    at android.os.Looper.loop(Looper.java:193)&#160;
    at android.app.ActivityThread.main(ActivityThread.java:6762)&#160;
    at java.lang.reflect.Method.invoke(Native Method)&#160;
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)&#160;

答案1

得分: 2

使用Parcelable而不是Serializable已经解决了这个问题。然而,当导航时,我仍然会收到一个IllegalArgumentException异常,显示:“无法从当前目标找到当前动作/目标”。但它不会导致应用崩溃或造成任何副作用(至少在我的应用中是如此,我建议你运行测试用例)。

注意:以防万一,我已经将这个代码块包裹在try-catch中。

初始化对话框片段的代码:

try
{
    Navigation.findNavController(binding.root).navigate(GameFragmentDirections.actionGameFragmentToPauseDialogFragment(
            object : PauseDialogFragment.ResumeGameListener
            {
                override fun onResume()
                {
                    isGamePaused = false
                    onStartGame(_screenSizePairXY)
                }

                override fun writeToParcel(p0: Parcel?, p1: Int)
                {
                }

                override fun describeContents(): Int = 0
            }))

}
catch (e: Exception)
{
    Timber.w(e.fillInStackTrace())
}

Parcelable回调接口:

interface ResumeGameListener : Parcelable
{
    fun onResume()
}
英文:

Using Parcelable instead of Serializable has solved the issue. However, I still do get an IllegalArgumentException exception saying: "current action/destination cannot be found from the current destination" when navigating.
<br>But it doesn't crash the app or cause any kind of side effects (at least in my app, I'd suggest you run test cases).

Note: Just in case I have wrapped the block in try-catch.

Code to init dialog fragment:

   try
        {
            Navigation.findNavController(binding.root).navigate(GameFragmentDirections.actionGameFragmentToPauseDialogFragment(
                    object : PauseDialogFragment.ResumeGameListener
                    {
                        override fun onResume()
                        {
                            isGamePaused = false
                            onStartGame(_screenSizePairXY)
                        }

                        override fun writeToParcel(p0: Parcel?, p1: Int)
                        {
                        }

                        override fun describeContents(): Int = 0
                    }))

        }
        catch (e: Exception)
        {
            Timber.w(e.fillInStackTrace())
        }

Parcelable Callback Interface:

 interface ResumeGameListener : Parcelable
    {
        fun onResume()
    }

huangapple
  • 本文由 发表于 2020年9月12日 01:27:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/63851729.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定