Real‑world examples of null pointer exception in Android development

If you build Android apps long enough, you will eventually collect your own personal museum of null pointer horror stories. This guide walks through real, modern examples of null pointer exception in Android development, showing not just the stack traces but why they happen and how to stop repeating the same mistakes. These examples of everyday bugs come from common patterns: view binding gone wrong, lifecycle confusion, coroutines firing too late, and dependency injection misconfigurations. Instead of hand‑wavy theory, we’ll look at real examples that you can recognize in your own codebase, including the best examples that show how a single nullable value can cascade into crashes in production. Along the way, we’ll connect these Android‑specific problems to general null safety practices from the broader software world, and point you to external resources from universities and standards bodies that reinforce why defensive programming still matters in 2024 and 2025.
Written by
Jamie
Published

The most common real examples of NullPointerException in Android

Let’s start where Android developers actually feel pain: real examples of null pointer exception in Android development that show up in crash logs, usually five minutes after a release goes live.

A classic example of a null pointer exception looks like this in Logcat:

java.lang.NullPointerException: Attempt to invoke virtual method 
'void android.widget.TextView.setText(java.lang.CharSequence)'
 on a null object reference
    at com.example.app.ui.ProfileFragment.updateName(ProfileFragment.kt:74)

The stack trace is boringly familiar, but the context matters. In 2024–2025, most Android projects are using Kotlin, coroutines, and some flavor of dependency injection. That stack makes certain patterns more likely to trigger these errors if you’re not careful.


View binding and lifecycle: the best examples from Fragments

One of the best examples of null pointer exception in Android development comes from misusing view binding in Fragments. The pattern usually looks like this:

class ProfileFragment : Fragment(R.layout.fragment_profile) {
    private var _binding: FragmentProfileBinding? = null
    private val binding get() = _binding!!

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        _binding = FragmentProfileBinding.bind(view)

        viewModel.user.observe(viewLifecycleOwner) { user ->
            binding.nameText.text = user.name
        }
    }

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

This looks fine, and most of the time it is. The problem appears when an asynchronous callback fires after onDestroyView has run. The LiveData or coroutine still tries to access binding, which now resolves to null under the hood, and your !! operator happily throws a NullPointerException.

Real examples include:

  • A network call finishes after the user navigates away.
  • A long‑running animation callback references the binding after rotation.
  • A Flow collected in lifecycleScope.launch is not tied to the viewLifecycleOwner.

Fix the pattern, not just the crash:

viewLifecycleOwner.lifecycleScope.launch {
    viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.userFlow.collectLatest { user ->
            binding?.nameText?.text = user.name
        }
    }
}

Here, the collector is automatically canceled when the view is destroyed, and we also stop pretending binding can never be null. This is one of the most instructive examples of how lifecycle awareness prevents null pointer exceptions in Android.


Activity intent extras: subtle examples include missing data

Another real example of null pointer exception in Android development hides in Intent extras. A typical pattern:

class DetailActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_detail)

        val id = intent.extras!!.getLong("ITEM_ID")
        loadItem(id)
    }
}

This works until someone launches DetailActivity from a new entry point and forgets to put ITEM_ID in the extras. Suddenly, you’re reading crash reports from production with a null pointer exception coming from .extras!!.

Better patterns avoid assuming extras exist:

val id = intent?.getLongExtra("ITEM_ID", -1L)
if (id == null || id == -1L) {
    finish() // or show error UI
    return
}

In many codebases, some of the best examples of hidden null pointer risks are these “it always exists” assumptions around Intent data.


Kotlin lateinit gone wrong: a modern example of self‑inflicted NPE

Kotlin tries hard to reduce null pointer exceptions, but lateinit gives you enough rope to hang your app. Consider this simplified view‑model setup:

class DashboardFragment : Fragment(R.layout.fragment_dashboard) {
    private lateinit var adapter: DashboardAdapter

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        recyclerView.adapter = adapter
    }
}

If you forget to initialize adapter before using it, Kotlin throws an UninitializedPropertyAccessException, which is basically a null pointer exception in nicer clothing.

Real examples of this pattern include:

  • lateinit properties for adapters, presenters, or controllers that are only initialized in some code paths.
  • ViewModels with lateinit repositories that depend on injection that may fail.

A safer approach uses constructor injection or nullable types with safe access:

class DashboardFragment @Inject constructor(
    private val adapter: DashboardAdapter
) : Fragment(R.layout.fragment_dashboard) {
    // adapter is always initialized now
}

This aligns with the broader software engineering advice you’ll find in resources like Carnegie Mellon’s SEI guidance on defensive programming, where avoiding partially initialized state is a recurring theme.


Coroutines, ViewModel, and late UI attachment

In 2024–2025, many of the most interesting examples of null pointer exception in Android development involve coroutines. A common pattern:

class FeedFragment : Fragment(R.layout.fragment_feed) {
    private var _binding: FragmentFeedBinding? = null
    private val binding get() = _binding!!

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        _binding = FragmentFeedBinding.bind(view)

        viewModel.feedState.observe(viewLifecycleOwner) { state ->
            render(state)
        }

        viewModel.loadFeed() // launches coroutine
    }

    private fun render(state: FeedState) {
        binding.progressBar.isVisible = state.isLoading
        binding.recyclerView.isVisible = state.items.isNotEmpty()
    }
}

Now imagine loadFeed() launches a coroutine in the ViewModel’s scope, which emits updates even after the Fragment’s view is destroyed on configuration change. If render is called after _binding is set to null in onDestroyView, you’ve got another null pointer exception.

Cleaner patterns:

  • Use viewLifecycleOwner.lifecycleScope and repeatOnLifecycle for UI collectors.
  • Avoid !! on bindings; prefer nullable binding with safe calls.

This problem is essentially the Android‑flavored version of race conditions described in general programming literature, such as examples discussed in MIT’s open courseware on software construction and concurrency (MIT OpenCourseWare). Different stack, same underlying bug: state changes outliving their expected lifetime.


Dependency Injection misconfigurations: when DI gives you nulls

Modern Android apps lean heavily on Dagger/Hilt, Koin, or other DI frameworks. That brings a new family of examples of null pointer exception in Android development: dependencies that are assumed to be injected but aren’t.

Typical scenario:

@AndroidEntryPoint
class SettingsFragment : Fragment(R.layout.fragment_settings) {

    @Inject
    lateinit var analytics: AnalyticsLogger

    override fun onResume() {
        super.onResume()
        analytics.logScreen("settings")
    }
}

If someone forgets the @AndroidEntryPoint annotation on the Fragment, analytics never gets initialized. The first call to analytics.logScreen throws.

Real examples include:

  • Missing @AndroidEntryPoint on Activities or Fragments.
  • Injecting into custom views without proper Hilt setup.
  • Using by viewModels() without @HiltViewModel on the ViewModel.

The fix is less about clever null checks and more about consistent DI configuration and tests that actually instantiate these components the way the app does.


RecyclerView and ViewHolder patterns: adapter fields that go null

RecyclerView adapters are another fertile ground for examples of null pointer exception in Android development. A familiar anti‑pattern looks like this:

class ChatAdapter : RecyclerView.Adapter<ChatViewHolder>() {

    var listener: OnMessageClickListener? = null

    override fun onBindViewHolder(holder: ChatViewHolder, position: Int) {
        val item = items[position]
        holder.itemView.setOnClickListener {
            listener!!.onMessageClick(item) // boom
        }
    }
}

If listener is never set, or is cleared when the parent Fragment is destroyed but the adapter outlives it, you get a null pointer exception as soon as the user taps an item.

Better:

listener?.onMessageClick(item)

Or, if the listener is mandatory, inject it via the constructor and make it non‑nullable:

class ChatAdapter(
    private val listener: OnMessageClickListener
) : RecyclerView.Adapter<ChatViewHolder>() { ... }

These are small changes, but they remove entire classes of null pointer bugs that otherwise show up as some of the best examples in your crash analytics dashboard.


Network responses and mapping: server data as a source of nulls

Not all nulls are your fault. Some come from APIs that don’t behave the way their docs promise. Real examples of null pointer exception in Android development often involve assumptions about non‑null fields in JSON responses.

Imagine this DTO:

data class UserDto(
    val id: String,
    val name: String,
    val avatarUrl: String
)

Your backend quietly starts omitting avatarUrl for some users. Your JSON parser sets it to null, but your Kotlin model says it can’t be null. Depending on the parser, you might get a null pointer exception either in parsing or when you later call user.avatarUrl.length.

Safer mapping in modern code:

data class UserDto(
    val id: String?,
    val name: String?,
    val avatarUrl: String?
)

fun UserDto.toDomain(): User = User(
    id = id.orEmpty(),
    name = name ?: "Unknown",
    avatarUrl = avatarUrl
)

Then in UI code:

if (user.avatarUrl != null) {
    imageLoader.load(imageView, user.avatarUrl)
} else {
    imageView.setImageResource(R.drawable.placeholder)
}
``;

These patterns echo general defensive coding principles you’ll find in university curricula and software engineering texts, where input validation is repeatedly highlighted as a way to avoid null‑related crashes.

---

## Configuration changes and async tasks: old but still real examples

Even in 2025, legacy patterns like `AsyncTask` or manually managed background threads still exist in long‑lived apps. They provide some of the oldest but still relevant examples of null pointer exception in Android development.

Typical pattern:

```java
public class LegacyActivity extends Activity {
    private TextView statusView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_legacy);
        statusView = findViewById(R.id.status);

        new LoadTask().execute();
    }

    private class LoadTask extends AsyncTask<Void, Void, String> {
        @Override
        protected String doInBackground(Void... voids) {
            // long network call
            return "Done";
        }

        @Override
        protected void onPostExecute(String result) {
            statusView.setText(result); // may be null after rotation
        }
    }
}

Rotate the device during the network call, and statusView may no longer exist when onPostExecute runs. The Activity might be destroyed and recreated, leaving statusView as null in the old instance.

Modern fixes involve:

  • Moving work into a ViewModel and exposing state via LiveData or Flow.
  • Using lifecycle‑aware scopes (lifecycleScope, viewLifecycleOwner.lifecycleScope).

These patterns are strongly aligned with the general guidance on safe concurrent programming you’ll see in academic and industry resources.


Why null pointer exceptions still matter in 2024–2025

You’d think Kotlin and better tooling would have wiped out these bugs by now. Yet, crash analytics for real apps still show null pointer exceptions as one of the top causes of runtime failures. Industry surveys and large‑scale bug studies (for example, those cited in software reliability research at institutions like Harvard University) consistently highlight null dereferences as a persistent class of defects.

Modern Android development adds:

  • More async layers (coroutines, Flows, RxJava) → more timing windows where objects can go null.
  • More DI and modularization → more configuration paths where something can be missing.
  • More entry points (deep links, widgets, notifications, multi‑window) → more ways to launch screens without the data you assume.

The best examples of null pointer exception in Android development today are rarely just “forgot to check for null.” They’re about incorrectly modeled lifecycles, incorrect assumptions about external data, and overconfidence in !! and lateinit.


Practical habits to reduce these examples in your own app

A few habits dramatically cut down on real examples of null pointer exception in Android development:

  • Prefer constructor injection over field injection and lateinit.
  • Treat !! as a code smell; if you need it, ask why.
  • Tie async work to the correct lifecycle owner.
  • Model external data as nullable at the edge, then sanitize it in mappers.
  • Add tests that launch Activities/Fragments the way the system does, including via deep links and notifications.

Outside mobile, similar advice appears in secure coding standards from organizations like NIST, where unchecked assumptions about input and state are a recurring root cause of bugs and vulnerabilities. The domain is different; the pattern is the same.


FAQ: examples of common questions about Android NPEs

Q: What is a simple example of a null pointer exception in Android?
A basic example is calling findViewById before setContentView in an Activity, then doing textView.setText("Hi"). Since the view hierarchy isn’t inflated yet, textView is null and the call throws.

Q: Are Kotlin apps safe from null pointer exceptions?
Kotlin reduces the surface area, but it doesn’t eliminate the problem. lateinit, !!, platform types from Java, and misconfigured dependencies all produce real examples of null pointer exception in Android development, even in pure Kotlin projects.

Q: What are the most frequent examples of NPEs you see in production apps?
The most frequent examples include Fragment view binding used after onDestroyView, missing intent extras accessed with !!, null listeners in adapters, and network responses that omit fields the app expects to be non‑null.

Q: How can I systematically find these issues before release?
Static analysis tools (like Android Lint and IDE inspections) catch some patterns. Unit and instrumentation tests that simulate configuration changes, background/foreground transitions, and alternate entry points catch many of the best examples of lifecycle‑related null pointer exceptions.

Q: Is it better to make everything nullable and check, or use non‑null types aggressively?
At the boundaries (network, database, intents), model data as nullable and normalize it. Inside your domain layer, prefer non‑null types and construct them only from validated data. This balance keeps null pointer exceptions rare without turning your code into a maze of ?. and ?:.

Explore More Null Pointer Exceptions

Discover more examples and insights in this category.

View All Null Pointer Exceptions