mapbox / mapbox/mapbox-navigation-android

com.mapbox.navigation.ui:1.6.1 crash during configurations change

Open
#5,287 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Kotlin
Stars
651
Forks
321
PR merge metrics
No merged PRs in 30d

Description

**Android API: 29+**
**com.mapbox.navigation.ui:1.6.1**

### Steps to trigger behavior

1. Create a `com.mapbox.navigation.ui.NavigationView` in a new fragment
2. Wait for the night, so the device will go into a dark mode(don't listen for configurations changes in the activity)
3. Call to start navigation after the fragment was recreated

### Expected behavior
No crashing

### Actual behavior
A crash

```
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.mapbox.navigation.ui.NavigationViewEventDispatcher.onNavigationFinished()' on a null object reference
at com.mapbox.navigation.ui.NavigationViewModel$3.onSessionStateChanged(NavigationViewModel.java:531)
at com.mapbox.navigation.core.trip.session.MapboxTripSession.registerStateObserver(MapboxTripSession.kt:309)
at com.mapbox.navigation.core.MapboxNavigation.registerTripSessionStateObserver(MapboxNavigation.kt:519)
at com.mapbox.navigation.ui.NavigationViewModel.addNavigationListeners(NavigationViewModel.java:448)
at com.mapbox.navigation.ui.NavigationViewModel.initializeNavigation(NavigationViewModel.java:438)
at com.mapbox.navigation.ui.NavigationViewModel.initialize(NavigationViewModel.java:220)
at com.mapbox.navigation.ui.NavigationView.initializeNavigation(NavigationView.java:935)
at com.mapbox.navigation.ui.NavigationView.startNavigation(NavigationView.java:497)
```

### Why do I think this is happening?
During fragment recreation, a new view is created before the old view is destroyed.
After the old view is destroyed it calls to `com.mapbox.navigation.ui.NavigationViewModel.onDestroy`. It sets the `navigationViewEventDispatcher` to `null`.
When the new view calls to `startNavigation` the app is crashing because `navigationViewEventDispatcher` is `null`.

The `NavigationViewModel` is using an activity life cycle, so you should not couple it with the View life cycle. I bet this causes a bunch of other bugs as well.

## A workaround

Before starting navigation, check for this bug and attempt to reinitialize the view

### Check for the bug
```
fun isNavigationViewEventDispatcherNullBug(): Boolean {
val navigationViewModel =
ViewModelProvider(requireActivity()).get(NavigationViewModel::class.java)
val field = navigationViewModel.javaClass.getDeclaredField("navigationViewEventDispatcher")
field.isAccessible = true
return field.get(navigationViewModel) == null
}
```
### Reinitialize the view
```
fun reinitializeNavigationView() {
val methods = NavigationView::class.java.declaredMethods
methods.filter {
arrayOf(
"initializeNavigationEventDispatcher",
"initializeInstructionListener",
"initializeSummaryBottomSheet"
).contains(it.name)
}.forEach {
it.isAccessible = true
it.invoke(navigationView)
}
}
```

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing NavigationViewModel.onDestroy, initializeNavigation, and addNavigationListeners, then compare their activity and view lifecycle behavior during Fragment recreation. Reproduce the dark-mode configuration change with NavigationView and startNavigation. Done means the recreated view starts navigation without the navigationViewEventDispatcher null crash.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, kotlin
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.