fragment 异常 InstantiationException

接手的项目过了下firebase和内存泄漏,还是有很多常见共性的问题

 这个异常也是非常常见,但是很多人不会去修复的

Caused by: androidx.fragment.app.Fragment$InstantiationException: Unable to instantiate fragment com.healthfitness.me.ui.badgeinfo.BadgeListInfoDialog: could not find Fragment constructor
                 	at androidx.fragment.app.Fragment.instantiate(Fragment.java:687)
                 	at androidx.fragment.app.FragmentContainer.instantiate(FragmentContainer.java:57)
                 	at androidx.fragment.app.FragmentManager$3.instantiate(FragmentManager.java:525)
                 	at androidx.fragment.app.FragmentState.instantiate(FragmentState.java:84)
                 	at androidx.fragment.app.FragmentStateManager.<init>(FragmentStateManager.java:91)
                 	at androidx.fragment.app.FragmentManager.restoreSaveStateInternal(FragmentManager.java:2562)
                 	at androidx.fragment.app.Fragment.restoreChildFragmentState(Fragment.java:1988)
                 	at androidx.fragment.app.Fragment.onCreate(Fragment.java:1967)
                 	at androidx.fragment.app.Fragment.performCreate(Fragment.java:3094)
                 	at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:504)
                 	at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:268)

原因是

  • Android 系统在重建 Fragment 时,只能通过无参构造函数反射生成实例
  • 如果自定义了带参数的构造函数,系统无法找到无参构造方法,直接崩溃。

  • 通过 Bundle 传递参数是 Android 的官方推荐做法。

比如很常见的


class BadgeListInfoDialog(
    private val uId: Long,
    private val bId: Long,
    private val isMe: Boolean = true,//表示查看自己的
    private val badgeUserInfo: BadgeUserInfo? = null,//个人信息
    private val equipBId: Long?=null,
    private val mBadgeDetailBean: BadgeDetailBean?=null,//勋章详情,如果外层已经获取到了,就不用再请求了
    private val isDisBadgeBid: Long?=null
) : BaseDialogFragment<DialogBadgeListInfoBinding>()

BadgeListInfoDialog有了有参数的构造函数,就没有了默认的无参构造函数

所以比如页面销毁重建的时候,就会报这个异常

改造方案

class BadgeListInfoDialog : BaseDialogFragment<DialogBadgeListInfoBinding>() {
    // 定义参数 Key(避免硬编码)
    companion object {
        private const val KEY_UID = "uId"
        private const val KEY_BID = "bId"
        private const val KEY_IS_ME = "isMe"
        private const val KEY_BADGE_USER_INFO = "badgeUserInfo"
        private const val KEY_EQUIP_BID = "equipBId"
        private const val KEY_BADGE_DETAIL_BEAN = "badgeDetailBean"
        private const val KEY_IS_DIS_BADGE_BID = "isDisBadgeBid"

        // 统一的创建方法
        fun newInstance(
            uId: Long,
            bId: Long,
            isMe: Boolean = true,
            badgeUserInfo: BadgeUserInfo? = null,
            equipBId: Long? = null,
            badgeDetailBean: BadgeDetailBean? = null,
            isDisBadgeBid: Long? = null
        ): BadgeListInfoDialog {
            val args = Bundle().apply {
                putLong(KEY_UID, uId)
                putLong(KEY_BID, bId)
                putBoolean(KEY_IS_ME, isMe)
                putParcelable(KEY_BADGE_USER_INFO, badgeUserInfo)
                equipBId?.let { putLong(KEY_EQUIP_BID, it) }
                putSerializable(KEY_BADGE_DETAIL_BEAN, badgeDetailBean)
                isDisBadgeBid?.let { putLong(KEY_IS_DIS_BADGE_BID, it) }
            }
            return BadgeListInfoDialog().apply {
                arguments = args
            }
        }
    }

    // 其他代码...
}

在oncreate中

class BadgeListInfoDialog : BaseDialogFragment<DialogBadgeListInfoBinding>() {
    // 定义参数变量(添加 lateinit 或可空类型)
    private lateinit var uId: Long
    private lateinit var bId: Long
    private var isMe: Boolean = true
    private var badgeUserInfo: BadgeUserInfo? = null
    private var equipBId: Long? = null
    private var mBadgeDetailBean: BadgeDetailBean? = null
    private var isDisBadgeBid: Long? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 从 Bundle 中解析参数
        arguments?.let { args ->
            uId = args.getLong(KEY_UID)
            bId = args.getLong(KEY_BID)
            isMe = args.getBoolean(KEY_IS_ME, true)
            badgeUserInfo = args.getParcelable(KEY_BADGE_USER_INFO)
            equipBId = if (args.containsKey(KEY_EQUIP_BID)) args.getLong(KEY_EQUIP_BID) else null
            mBadgeDetailBean = args.getSerializable(KEY_BADGE_DETAIL_BEAN) as? BadgeDetailBean
            isDisBadgeBid = if (args.containsKey(KEY_IS_DIS_BADGE_BID)) args.getLong(KEY_IS_DIS_BADGE_BID) else null
        }
    }

    // 其他代码...
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值