Skip to content

Commit

Permalink
Create a delegate for MapboxNavigation
Browse files Browse the repository at this point in the history
  • Loading branch information
kmadsen committed Aug 25, 2022
1 parent f68ed19 commit 0f6a748
Show file tree
Hide file tree
Showing 6 changed files with 560 additions and 71 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Mapbox welcomes participation and contributions from everyone.

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

#### Bug fixes and improvements

## Mapbox Navigation SDK 2.8.0-beta.1 - 25 August, 2022
Expand Down
9 changes: 9 additions & 0 deletions libnavigation-core/api/current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,15 @@ package com.mapbox.navigation.core.lifecycle {
method public com.mapbox.navigation.base.options.NavigationOptions createNavigationOptions();
}

public final class RequireMapboxNavigationProperty implements kotlin.properties.ReadOnlyProperty<androidx.lifecycle.LifecycleOwner,com.mapbox.navigation.core.MapboxNavigation> {
ctor public RequireMapboxNavigationProperty(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 public com.mapbox.navigation.core.MapboxNavigation getValue(androidx.lifecycle.LifecycleOwner thisRef, kotlin.reflect.KProperty<?> property);
}

public final class RequireMapboxNavigationPropertyKt {
method public static com.mapbox.navigation.core.lifecycle.RequireMapboxNavigationProperty 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);
}

}

package com.mapbox.navigation.core.navigator {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package com.mapbox.navigation.core.lifecycle

import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import com.mapbox.navigation.core.MapboxNavigation
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty

/**
* Extension function to make it simple to create the [RequireMapboxNavigationProperty]. Below are
* a couple examples of how you may use the delegate.
*
* Default can be used when [MapboxNavigationApp] is setup elsewhere.
* ```
* val mapboxNavigation by requireMapboxNavigation()
* ```
*
* Initialize the [MapboxNavigationApp] when you are ready to use it
* ```
* val mapboxNavigation by requireMapboxNavigation {
* MapboxNavigationApp.setup(..)
* }
* ```
*
* Register subscriptions and setup MapboxNavigationApp
* ```
* private val mapboxNavigation by requireMapboxNavigation(
* onResumedObserver = object : MapboxNavigationObserver {
* override fun onAttached(mapboxNavigation: MapboxNavigation) {
* mapboxNavigation.registerLocationObserver(locationObserver)
* mapboxNavigation.registerRoutesObserver(routesObserver)
* }
* override fun onDetached(mapboxNavigation: MapboxNavigation) {
* mapboxNavigation.unregisterLocationObserver(locationObserver)
* mapboxNavigation.unregisterRoutesObserver(routesObserver)
* }
* }
* ) {
* MapboxNavigationApp.setup(
* NavigationOptions.Builder(this)
* .accessToken(accessToken)
* .build()
* )
* }
* ```
*
* @see [RequireMapboxNavigationProperty] for more details.
*/
fun requireMapboxNavigation(
onCreatedObserver: MapboxNavigationObserver? = null,
onStartedObserver: MapboxNavigationObserver? = null,
onResumedObserver: MapboxNavigationObserver? = null,
onInitialize: () -> Unit
) = RequireMapboxNavigationProperty(
onCreatedObserver = onCreatedObserver,
onStartedObserver = onStartedObserver,
onResumedObserver = onResumedObserver,
onInitialize = onInitialize
)

/**
* Creates a simple way to use the [MapboxNavigationApp] inside a [LifecycleOwner] and provides
* access to [MapboxNavigation].
*
* You can choose to call [MapboxNavigationApp.setup] in the [onInitialize]. You can also setup in
* the onCreate calls, or any call that happens before this delegate is accessed. The delegate will
* crash if the app is not setup and an attached has been created.
*
* You can use the observers parameter to setup any subscriptions. This is important because the
* [MapboxNavigation] instance can be re-created with [MapboxNavigationApp.disable], or if all
* [MapboxNavigationApp.attach] lifecycles are destroyed.
*
* @param onCreatedObserver to setup any subscriptions when the lifecycle [Lifecycle.State.CREATED]
* @param onStartedObserver to setup any subscriptions when the lifecycle [Lifecycle.State.STARTED]
* @param onResumedObserver to setup any subscriptions when the lifecycle [Lifecycle.State.RESUMED]
* @param onInitialize called after the lifecycle has been attached
*/
class RequireMapboxNavigationProperty(
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

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

override fun onDestroy(owner: LifecycleOwner) {
onCreatedObserver?.let { MapboxNavigationApp.unregisterObserver(it) }
}

override fun onStart(owner: LifecycleOwner) {
onStartedObserver?.let { MapboxNavigationApp.registerObserver(it) }
}

override fun onStop(owner: LifecycleOwner) {
onStartedObserver?.let { MapboxNavigationApp.unregisterObserver(it) }
}

override fun onResume(owner: LifecycleOwner) {
onResumedObserver?.let { MapboxNavigationApp.registerObserver(it) }
}

override fun onPause(owner: LifecycleOwner) {
onResumedObserver?.let { MapboxNavigationApp.unregisterObserver(it) }
}
}

override fun getValue(thisRef: LifecycleOwner, property: KProperty<*>): MapboxNavigation {
if (!this::lifecycleOwner.isInitialized) {
onInitialize?.invoke()
this.lifecycleOwner = thisRef
MapboxNavigationApp.attach(lifecycleOwner)
lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
}
val mapboxNavigation = MapboxNavigationApp.current()
checkNotNull(mapboxNavigation) {
"MapboxNavigation cannot be null. Ensure that MapboxNavigationApp is setup and an" +
" attached lifecycle is at least CREATED."
}
return mapboxNavigation
}
}
Loading

0 comments on commit 0f6a748

Please sign in to comment.