Skip to content

Commit

Permalink
Make requireMapboxNavigation attach during initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
kmadsen committed Sep 6, 2022
1 parent b145c53 commit 8dbc73a
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 21 deletions.
1 change: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ Mapbox welcomes participation and contributions from everyone.
## Unreleased
#### Features
- Improved the route refresh feature to also refresh _closures_ (`RouteLeg#closures`). [#6274](https://github.com/mapbox/mapbox-navigation-android/pull/6274)

- Added `requireMapboxNavigation` to offer a simple way to use `MapboxNavigationApp`. [#6233](https://github.com/mapbox/mapbox-navigation-android/pull/6233)
#### Bug fixes and improvements

Expand Down
2 changes: 1 addition & 1 deletion libnavigation-core/api/current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ package com.mapbox.navigation.core.lifecycle {
}

public final class RequireMapboxNavigation {
method @com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI public static kotlin.properties.ReadOnlyProperty<androidx.lifecycle.LifecycleOwner,com.mapbox.navigation.core.MapboxNavigation> requireMapboxNavigation(com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver? onCreatedObserver = null, com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver? onStartedObserver = null, com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver? onResumedObserver = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onInitialize = null);
method @com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI public static kotlin.properties.ReadOnlyProperty<java.lang.Object,com.mapbox.navigation.core.MapboxNavigation> requireMapboxNavigation(androidx.lifecycle.LifecycleOwner, com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver? onCreatedObserver = null, com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver? onStartedObserver = null, com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver? onResumedObserver = null, kotlin.jvm.functions.Function0<kotlin.Unit>? onInitialize = null);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
import com.mapbox.navigation.core.MapboxNavigation
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp.lifecycleOwner
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty

/**
* Extension function to make it simple to create the [RequireMapboxNavigationDelegate]. Below are
* a couple examples of how you may use the delegate.
* Extension function to make it simple to create the [RequireMapboxNavigationDelegate].
* Below are a couple examples of how you may use the delegate.
*
* Default can be used when [MapboxNavigationApp] is setup elsewhere.
* ```
Expand Down Expand Up @@ -51,12 +52,13 @@ import kotlin.reflect.KProperty
* @see [RequireMapboxNavigationDelegate] for more details.
*/
@ExperimentalPreviewMapboxNavigationAPI
fun requireMapboxNavigation(
fun LifecycleOwner.requireMapboxNavigation(
onCreatedObserver: MapboxNavigationObserver? = null,
onStartedObserver: MapboxNavigationObserver? = null,
onResumedObserver: MapboxNavigationObserver? = null,
onInitialize: (() -> Unit)? = null,
): ReadOnlyProperty<LifecycleOwner, MapboxNavigation> = RequireMapboxNavigationDelegate(
): ReadOnlyProperty<Any, MapboxNavigation> = RequireMapboxNavigationDelegate(
lifecycleOwner = this,
onCreatedObserver = onCreatedObserver,
onStartedObserver = onStartedObserver,
onResumedObserver = onResumedObserver,
Expand All @@ -74,22 +76,23 @@ fun requireMapboxNavigation(
* [MapboxNavigation] instance can be re-created with [MapboxNavigationApp.disable], or if all
* [MapboxNavigationApp.attach] lifecycles are destroyed.
*
* @param lifecycleOwner: LifecycleOwner
* @param onCreatedObserver registered to the [Lifecycle.State.CREATED] lifecycle
* @param onStartedObserver registered to the [Lifecycle.State.STARTED] lifecycle
* @param onResumedObserver registered to the [Lifecycle.State.RESUMED] lifecycle
* @param onInitialize called when the property is read for the first time
* @param onInitialize called when the [lifecycleOwner] is [Lifecycle.State.CREATED]
*/
internal class RequireMapboxNavigationDelegate(
lifecycleOwner: LifecycleOwner,
private val onCreatedObserver: MapboxNavigationObserver? = null,
private val onStartedObserver: MapboxNavigationObserver? = null,
private val onResumedObserver: MapboxNavigationObserver? = null,
private val onInitialize: (() -> Unit)? = null
) : ReadOnlyProperty<LifecycleOwner, MapboxNavigation> {

private lateinit var lifecycleOwner: LifecycleOwner
) : ReadOnlyProperty<Any, MapboxNavigation> {

private val lifecycleObserver = object : DefaultLifecycleObserver {
override fun onCreate(owner: LifecycleOwner) {
onInitialize?.invoke()
onCreatedObserver?.let { MapboxNavigationApp.registerObserver(it) }
}

Expand All @@ -114,21 +117,19 @@ internal class RequireMapboxNavigationDelegate(
}
}

init {
MapboxNavigationApp.attach(lifecycleOwner)
lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
}

/**
* Returns an instance of [MapboxNavigation], the first retrieval will attach the [thisRef]
* to [MapboxNavigationApp.attach]. If [MapboxNavigationApp.isSetup] is false after all
* observers and initializers, this property getter will crash.
* Returns an instance of [MapboxNavigation]. If [MapboxNavigationApp.isSetup] is false after
* all observers and initializers, this property getter will crash.
*
* @param thisRef - the [LifecycleOwner] that needs access to [MapboxNavigation].
* @param property - ignored
*/
override fun getValue(thisRef: LifecycleOwner, property: KProperty<*>): MapboxNavigation {
if (!this::lifecycleOwner.isInitialized) {
onInitialize?.invoke()
this.lifecycleOwner = thisRef
MapboxNavigationApp.attach(lifecycleOwner)
lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
}
override fun getValue(thisRef: Any, property: KProperty<*>): MapboxNavigation {
val mapboxNavigation = MapboxNavigationApp.current()
checkNotNull(mapboxNavigation) {
"MapboxNavigation cannot be null. Ensure that MapboxNavigationApp is setup and an" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,18 @@ class RequireMapboxNavigationTest {
sut.mapboxNavigation
}

@Test
fun `onInitialize is called before first reference to the delegate`() {
mockMapboxNavigationAppBehavior()
val mockOnInitialize: (() -> Unit) = mockk(relaxed = true)
val sut = SystemUnderTest(onInitialize = mockOnInitialize)

MapboxNavigationApp.setup(mockk<NavigationOptions>())
sut.moveToState(Lifecycle.State.CREATED)

verify { mockOnInitialize.invoke() }
}

@Test
fun `multiple delegate references are the same instance`() {
mockMapboxNavigationAppBehavior()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ class InactiveRouteStylingActivity : AppCompatActivity() {
private val mapboxNavigation by requireMapboxNavigation(
onCreatedObserver = object : MapboxNavigationObserver {
override fun onAttached(mapboxNavigation: MapboxNavigation) {

mapboxNavigation.registerLocationObserver(locationObserver)
mapboxNavigation.registerRouteProgressObserver(routeProgressObserver)
mapboxNavigation.registerRouteProgressObserver(replayProgressObserver)
Expand Down

0 comments on commit 8dbc73a

Please sign in to comment.