在 DialogFragment 中按“最近使用的应用程序”按钮时出现 BadParcelableException

问题描述 投票:0回答:1

我正在尝试制作一个 DialogFragment,它可以在不同的片段中重用,而无需使用以下代码创建新的片段。

我要放在下面的所有代码都可以正常工作,按钮可以工作,文本也可以看到,问题是当我按下手机的“最近的应用程序”按钮时,应用程序崩溃并出现以下错误:

android.os.BadParcelableException: Parcelable encountered IOException writing serializable object(name = com.mypackage.models.MyDialogInfo)

我正在创建一个名为 MyCustomDialogFragment 的 DialogFragment,它接收 MyDialogInfo 模型作为参数。

class MyDialogInfo(
    val id:String,
    val title:String,
    val body:String, 
    val firstButton: ButtonInfo?=null, 
    val secondaryButton: ButtonInfo?= null
):Serializable

class ButtonInfo(
    val text:String?=null,
    val textCharSequence:CharSequence?=null,
    val callback: CallbackButton
):Serializable{
    
    interface CallbackButton{
        fun onAction()
    }
}

在 MyCustomDialogFragment 中,我接收参数并像这样使用它们:

private val args: MyCustomDialogFragmentArgs by navArgs()

override fun onViewCreated(view:View, savedInstanceState:Bundle?){
    super.onViewCreated(view,savedInstanceState)
    setUpPrimaryButton(args.dialoginfo.firstButton)
    setUpSecondaryButton(args.dialoginfo.secondaryButton)
}

private fun setUpPrimaryButton(button: ButtonInfo?){
    
    with(binding){
        if(button == null){
            btPrimary.hide()
        }else {
            btPrimary.show()
            btPrimary.text= button.text
            btPrimary.setOnClickListener{
                dismiss()
                args.dialoginfo.firstButton?.callback?.onAction()
            }
        }
    }
}

private fun setUpSecondaryButton(button: ButtonInfo?){
    
    with(binding){
        if(button == null){
            btSec.hide()
        }else {
            btSec.show()
            
            if(!button.text.isNullOrEmpty()){
                btSec.text = button.text
            }else if(!button.textChar.isNullOrEmpty()){
                 btSec.text = button.textChar
            }
      
            btSec.setOnClickListener{
                dismiss()
                args.dialoginfo.secondaryButton?.callback?.onAction()
            }
        }
    }
}

然后,在其他Fragment中,我这样使用这个DialogFragment:

private var customDialogInfo :MyDialogInfo?=null

override fun onViewCreated(view:View, savedInstanceState:Bundle?){
    super.onViewCreated(view,savedInstanceState)
    setUpButton()
}

private setUpButton(){
    btnDoSomething.setOnClickListener{
        goToCustomDialog(
            title = "Title",
            body = "Body",
            fistButton = ButtonInfo(
                text = "Text Button",
                callback = object: CallbackButton{
                    override fun onAction(){
                        //Do Something
                    }
                }
            ),
             secondaryButton = ButtonInfo(
                text = "Text Button 2",
                callback = object: CallbackButton{
                    override fun onAction(){
                        //Do Something
                    }
                }
            )
        )
    }
}


private fun goToCustomDialog(
    title:String,
    body:String, 
    firstButton: ButtonInfo?=null, 
    secondaryButton: ButtonInfo?= null
){
    customDialogInfo = MyDialogInfo(
        id= UUID.randomUUID().toString(),
        title = title,
        body = body,
        firstButton = firstButton,
        secondaryButton = secondaryButton
    )
    findNavController().navigate(R.id.custom_dialog_fragment, bundleOf(Pair("dialoginfo",customDialogInfo)))
}
android kotlin android-fragments badparcelableexception
1个回答
0
投票

在您的代码中,ButtonInfo 类实现了 Serialized,但它包含一个不可序列化的对象 (CallbackButton)。

要解决此问题,您应该重构代码以避免在可序列化类中使用不可序列化对象。这是建议的方法:

不要使用 CallbackButton 接口,而是为主要和辅助按钮操作创建单独的类:

sealed class ButtonAction : Serializable {
    object PrimaryButtonAction : ButtonAction() {
        fun onAction() {
            // Do Something for primary button
        }
    }

    object SecondaryButtonAction : ButtonAction() {
        fun onAction() {
            // Do Something for secondary button
        }
    }
}

更新 ButtonInfo 以使用 ButtonAction:

class ButtonInfo(
    val text: String? = null,
    val textCharSequence: CharSequence? = null,
    val action: ButtonAction
) : Serializable

在 DialogFragment 中,直接使用 ButtonInfo.action 来执行操作:

btPrimary.setOnClickListener {
    dismiss()
    button.action.onAction()
}

在 Fragment 中构建 ButtonInfo 时,请使用 ButtonAction 实例作为操作:

firstButton = ButtonInfo(
    text = "Text Button",
    action = ButtonAction.PrimaryButtonAction
),
secondaryButton = ButtonInfo(
    text = "Text Button 2",
    action = ButtonAction.SecondaryButtonAction
)
© www.soinside.com 2019 - 2024. All rights reserved.