NullPointerException in Kotlin Fragment: How to Defeat It and Not Go Crazy

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: "I did everything by the tutorial, but the app crashes!"

\n

If you've just started your journey in Android development with Kotlin, you've probably already encountered this moment. You write code following a tutorial, launch the app... and crash. In the logs — the coveted java.lang.NullPointerException (or its Kotlin equivalent). And the message: "Cannot read field… because the view is null".

\n

This is a real pain that has gathered thousands of views on Stack Overflow. Today we will analyze it once and for all. Why does a NullPointerException occur when accessing a View in a Fragment in Kotlin? And, most importantly, how to fix it so you can sleep peacefully.

\n

Let's go!

\n\n

Why does the error occur? The root of the evil — Lifecycle

\n

The main reason beginners get a NullPointerException in Kotlin Fragment is a misunderstanding of the fragment lifecycle. In an Activity, everything is simple: onCreate — and go ahead. In a Fragment, everything is trickier.

\n

A fragment goes through several stages:

\n
    \n
  • onCreateView() — here the layout is inflated (created).
  • \n
  • onViewCreated() — here the View definitely already exists.
  • \n
  • onDestroyView() — the View is destroyed (for example, during a screen rotation).
  • \n
\n

The most popular error is trying to access the View before the fragment has created its layout. For example, in the constructor or in the fragment's onCreate(). At this moment, view equals null — hence the crash.

\n

The second reason is a reference leak. You saved a reference to the View in a variable, and then the fragment was recreated, and the old reference leads nowhere.

\n\n

Typical example: what the problem looks like in code

\n

Imagine you have a simple fragment with a text field:

\n
class MyFragment : Fragment() {\n\n    private lateinit var myTextView: TextView\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        // ERROR! The view doesn't exist yet here\n        myTextView = requireView().findViewById(R.id.my_text_view)\n        myTextView.text = "Hello!"\n    }\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View? {\n        return inflater.inflate(R.layout.fragment_my, container, false)\n    }\n}
\n

This code will crash with a NullPointerException because requireView() in onCreate() returns null. The View hasn't been created yet!

\n\n

3 working ways to fix the error

\n

Let's look at three approaches that will guaranteed solve the problem of accessing a View in a Fragment.

\n\n

Method 1: Move the code to onViewCreated()

\n

The simplest and most correct way is to wait for the moment when the View definitely exists. The onViewCreated() method is called immediately after the layout is created.

\n
class MyFragment : Fragment() {\n\n    private lateinit var myTextView: TextView\n\n    override fun onCreateView(\n        inflater: LayoutInflater,\n        container: ViewGroup?,\n        savedInstanceState: Bundle?\n    ): View? {\n        return inflater.inflate(R.layout.fragment_my, container, false)\n    }\n\n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        super.onViewCreated(view, savedInstanceState)\n        // Now view is definitely not null!\n        myTextView = view.findViewById(R.id.my_text_view)\n        myTextView.text = "It works!"\n    }\n}
\n

Pros: simple, clear, always works.
\nCons: you need to remember about lateinit var and not forget to nullify references in onDestroyView() (otherwise a memory leak is possible).

\n\n

Method 2: Use View Binding (recommended)

\n

Blogs

Book Recommendations