dwvldg
dwvldg

Reputation: 317

NullPointerException when using Kotlin ViewBinding inside Fragment

I'm trying to add a click listener to a button inside my fragment using Kotlin view binding. I am setting the click listener in the onCreateView() method. When I do this I get a null pointer exception since the button is not created yet. I thought the Kotlin view binding takes care of the view initialization so the button should not be null?

Here is my code:

class FragmentStart : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_start, container, false)
        start_button.setOnClickListener(
            Navigation.createNavigateOnClickListener(R.id.action_fragmentStart_to_fragmentQuestion,null)
        )
        return view
    }
}

Here is the exception:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setOnClickListener(android.view.View$OnClickListener)' on a null object reference

Upvotes: 5

Views: 10917

Answers (3)

Zain
Zain

Reputation: 40878

Probably a bit different from the OP, but hopefully could give some clues in some other contexts. For me, this exception is triggered when the user toggles the night mode on some fragment; so the activity and that fragment are recreated.

The fragment has some UI staff (RecyclerViews, DrawerLayout, etc.) that reinitialized again in the onViewCreated() callback; however, at that point, the binding is null, and the exception is raised.

I got that solved by postponing any UI changes when the binding.root is ready to access:

binding.root.post {

    // Use here the binding object or any subordinate view
}

Upvotes: 0

Peter F
Peter F

Reputation: 4299

kotlinx synthetic under the hood resolves start_button like that:

getView()?.findViewById(R.id.start_button)

getView() returns the fragment's root view if that has been set. This only happens after onCreateView().

That's why views resolved by kotlinx synthetics can only be used in onViewCreated().

Upvotes: 0

ThuanPx
ThuanPx

Reputation: 22

Because the view has not been created yet. You should call the view in the onViewCreated () function. read more

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

start_button.setOnClickListener(
                Navigation.createNavigateOnClickListener(R.id.action_fragmentStart_to_fragmentQuestion,null)
            )
    }

Upvotes: 0

Related Questions