androidkotlinandroid-dialogfragmentandroid-viewbindingfragment-oncreateview

DialogFragment: "lateinit property binding has not been initialized" in onCreateDialog(), whereas binding is initiated in onViewCerated()


kotlin.UninitializedPropertyAccessException: lateinit property binding has not been initialized
        at space.rodionov.financialsobriety.ui.transaction.edittransaction.ChooseCategoryDialogFragment.onCreateDialog(ChooseCategoryDialogFragment.kt:57)

This error shows up when I navigate to the DialogFragment with RecyclerView in it. I need Dialog to contain the recyclerview with custom items from Room to choose between.

Why I face this error if I have initialized binding in onViewCreated, and what is the solution? Appreciate any help

my DialogFragment:

@AndroidEntryPoint
class ChooseCategoryDialogFragment : DialogFragment(), ChooseCategoryAdapter.OnItemClickListener {

    private val viewModel: ChooseCategoryViewModel by viewModels()

    lateinit var binding: FragmentChooseCategoryBinding

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

        binding = FragmentChooseCategoryBinding.bind(view)
        val chooseCatAdapter = ChooseCategoryAdapter(this)

        binding.apply {
            recyclerView.apply {
                adapter = chooseCatAdapter
                layoutManager = LinearLayoutManager(requireContext())
                setHasFixedSize(true)

                viewLifecycleOwner.lifecycleScope.launchWhenStarted {
                    viewModel.categories.collect {
                        val spends = it ?: return@collect

                        chooseCatAdapter.submitList(spends)
                        tvNoCategories.isVisible = spends.isEmpty()
                        recyclerView.isVisible = spends.isNotEmpty()
                    }
                }
            }
        }
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        super.onCreateDialog(savedInstanceState)

            return AlertDialog.Builder(requireContext())
                .setTitle(requireContext().resources.getString(R.string.choose_category))
                .setView(binding.root) // here is the 57th line that error message alludes to.
                .setNegativeButton(
                    requireContext().resources.getString(R.string.cancel_action),
                    null
                )
                .create()
    }   

    override fun onItemClick(category: Category) {
        // some action with object
    }
}

Solution

  • Try with the following code it will help you, onCreateDialog() executing before onViewCreated at that time you view is not create.

     lateinit var binding: FragmentChooseCategoryBinding
    
    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        _binding = FragmentChooseCategoryBinding.inflate(LayoutInflater.from(context))
        return AlertDialog.Builder(requireActivity())
            .setView(binding.root)
            .create()
    }
    
    override fun onDestroyView() {
        super.onDestroyView()
        binding = null
    }