我正在尝试制作一个 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)))
}
在您的代码中,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
)