You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android BottomSheetDialogFragment内ChipGroup二次打开崩溃问题修复

问题:BottomSheetDialogFragment二次打开时ChipGroup空指针崩溃

在Android应用的BottomSheetDialogFragment中包含ChipGroup组件,首次打开对话框时能正常选中目标Chip,但关闭后再次打开会抛出NullPointerException,错误指向代码行mealChipGroup.findViewById<Chip>(3).isChecked = true。需要排查并修复该问题。

问题代码

class MenuFragment : BottomSheetDialogFragment() {
    // Binding
    private var _binding: FragmentMenuBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        _binding = FragmentMenuBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // InitView
        binding.apply {
            setupChip(fillChipData(), mealChipGroup)
            mealChipGroup.findViewById<Chip>(3).isChecked = true
        }
    }

    private fun fillChipData(): MutableList<String> {
        return mutableListOf(
            "Item1", "Item2", "Item3", "Item4", "Item5"
        )
    }

    private fun setupChip(list: MutableList<String>, view: ChipGroup) {
        list.forEach {
            val chip = Chip(requireContext())
            chip.text = it
            view.addView(chip)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        _binding = null
    }
}

错误信息

java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.material.chip.Chip.setChecked(boolean)' on a null object reference
        at myapp.MenuFragment.onViewCreated(MenuFragment.kt:58)
        at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3128)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:552)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1899)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1823)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1760)
        at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:547)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6121)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)

问题原因

  1. 系统自动分配ID不可靠:首次打开时,系统为动态添加的Chip自动分配ID,碰巧存在ID为3的Chip;但Fragment销毁重建时,系统分配的ID会随机变化,二次打开时findViewById(3)无法找到对应Chip,返回null触发空指针。
  2. 重复添加Chip:每次打开Fragment都会调用setupChip,但未清空ChipGroup原有内容,多次打开后ChipGroup会堆积重复Chip,进一步导致ID匹配逻辑混乱。

修复方案

方案1:给Chip设置固定唯一ID

手动给每个Chip分配固定ID,彻底摆脱对系统自动生成ID的依赖:

private fun setupChip(list: MutableList<String>, view: ChipGroup) {
    // 先清空ChipGroup,避免重复添加
    view.removeAllViews()
    list.forEachIndexed { index, text ->
        val chip = Chip(requireContext())
        chip.text = text
        // 用固定前缀+索引设置唯一ID,避免和其他控件ID冲突
        chip.id = 1000 + index
        view.addView(chip)
    }
}

修改选中逻辑,使用对应的固定ID,并添加空安全调用:

// 要选中第三个Item(索引2),对应ID为1000+2=1002
mealChipGroup.findViewById<Chip>(1002)?.isChecked = true

方案2:通过子View索引获取Chip

由于Chip是按顺序添加的,可直接通过索引定位目标Chip,无需依赖ID:

binding.apply {
    setupChip(fillChipData(), mealChipGroup)
    // 第三个Chip的索引为2(从0开始计数),先判断子View数量避免越界
    if (mealChipGroup.childCount > 2) {
        val targetChip = mealChipGroup.getChildAt(2) as Chip
        targetChip.isChecked = true
    }
}

同样需要在setupChip开头添加view.removeAllViews()避免重复添加。

额外注意

  • 动态添加View前务必清空容器,避免重复View堆积;
  • 动态创建的View不要依赖系统自动分配的ID,尽量手动设置固定唯一ID;
  • 优先使用Kotlin空安全调用?.,即使找不到View也不会崩溃,可配合?:做兜底处理。

内容的提问来源于stack exchange,提问作者Dr.KeyOk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 17:15:33