Skip to content

Commit

Permalink
Improve navigation fragment performance
Browse files Browse the repository at this point in the history
  • Loading branch information
kylecorry31 committed Jan 19, 2024
1 parent 382ee40 commit 77c2a8e
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import com.kylecorry.trail_sense.shared.Position
import com.kylecorry.trail_sense.shared.QuickActionType
import com.kylecorry.trail_sense.shared.UserPreferences
import com.kylecorry.trail_sense.shared.colors.AppColor
import com.kylecorry.trail_sense.shared.data.TrackedState
import com.kylecorry.trail_sense.shared.declination.DeclinationFactory
import com.kylecorry.trail_sense.shared.declination.DeclinationUtils
import com.kylecorry.trail_sense.shared.extensions.onDefault
Expand Down Expand Up @@ -130,8 +131,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
R.drawable.ic_compass_icon
)
}
private var gpsStatusBadge: StatusBadge? = null
private var compassStatusBadge: StatusBadge? = null

// Diagnostics
private val errors by lazy { NavigatorUserErrors(this) }
Expand All @@ -146,9 +145,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
) { declination }
}


private var hasGpsUpdate = true

private var astronomyDataLoaded = false

private var lastOrientation: DeviceOrientation.Orientation? = null
Expand Down Expand Up @@ -181,6 +177,16 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
private val styleChooser by lazy { CompassStyleChooser(userPrefs.navigation, hasCompass) }
private val useTrueNorth by lazy { userPrefs.compass.useTrueNorth }


// State
private val bearingState = TrackedState(0f)
private val speedState = TrackedState(0f)
private val altitudeState = TrackedState(0f)
private val locationState = TrackedState(Coordinate.zero)
private val compassStatusState = TrackedState<StatusBadge?>(null)
private val gpsStatusState = TrackedState<StatusBadge?>(null)


private val northReferenceHideTimer = CoroutineTimer {
if (isBound) {
binding.northReferenceIndicator.showLabel = false
Expand Down Expand Up @@ -293,11 +299,11 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {

navController = findNavController()

observe(compass) {}
observe(compass) { bearingState.write(compass.rawBearing) }
observe(orientation) { onOrientationUpdate() }
observe(altimeter) { }
observe(gps) { onLocationUpdate() }
observe(speedometer) { }
observe(altimeter) { altitudeState.write(altimeter.altitude) }
observe(gps) { locationState.write(gps.location) }
observe(speedometer) { speedState.write(speedometer.speed.speed) }

binding.navigationTitle.subtitle.setOnLongClickListener {
Share.shareLocation(
Expand Down Expand Up @@ -496,6 +502,7 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
}

// Populate the last known location
locationState.write(gps.location)
layerManager?.onLocationChanged(gps.location, gps.horizontalAccuracy)

// Resume navigation
Expand Down Expand Up @@ -608,6 +615,7 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
return
}

// TODO: Move selected beacon updating to a coroutine
val selectedBeacon = getSelectedBeacon(nearbyBeacons)

if (selectedBeacon != null) {
Expand All @@ -621,71 +629,119 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
binding.navigationSheet.hide()
}

gpsStatusBadge?.let {
binding.gpsStatus.setStatusText(it.name)
binding.gpsStatus.setBackgroundTint(it.color)
// GPS Status
if (gpsStatusState.hasChanges) {
gpsStatusState.read()?.let {
binding.gpsStatus.setStatusText(it.name)
binding.gpsStatus.setBackgroundTint(it.color)
}
}

compassStatusBadge?.let {
binding.compassStatus.setStatusText(it.name)
binding.compassStatus.setBackgroundTint(it.color)
// Compass Status
if (compassStatusState.hasChanges) {
compassStatusState.read()?.let {
binding.compassStatus.setStatusText(it.name)
binding.compassStatus.setBackgroundTint(it.color)
}
}

// Speed
binding.speed.title = formatService.formatSpeed(speedometer.speed.speed)
if (speedState.hasChanges) {
binding.speed.title = formatService.formatSpeed(speedState.read())
}

// Azimuth
if (bearingState.hasChanges) {
updateCompassBearing()
}

// Altitude
if (altitudeState.hasChanges) {
binding.altitude.title = formatService.formatDistance(
Distance.meters(altitudeState.read()).convertTo(baseDistanceUnits)
)
}

// Location
if (locationState.hasChanges) {
updateLocation()
}

updateNavigationButton()

// show on lock screen
if (lockScreenPresence && (destination != null || destinationBearing != null)) {
activity?.let {
tryOrNothing {
Screen.setShowWhenLocked(it, true)
}
}
}

sightingCompass?.update()
}

private fun updateCompassBearing() {
val bearing = Bearing(bearingState.read())

// Azimuth
if (hasCompass) {
val azimuthText =
formatService.formatDegrees(compass.bearing.value, replace360 = true)
formatService.formatDegrees(bearing.value, replace360 = true)
.padStart(4, ' ')
val directionText = formatService.formatDirection(compass.bearing.direction)
val directionText = formatService.formatDirection(bearing.direction)
.padStart(2, ' ')
binding.navigationTitle.title.setTextDistinct("$azimuthText $directionText")
} else {
binding.navigationTitle.title.setTextDistinct(getString(R.string.dash))
}

// Altitude
binding.altitude.title = formatService.formatDistance(
Distance.meters(altimeter.altitude).convertTo(baseDistanceUnits)
)

layerManager?.onBearingChanged(compass.bearing)
layerManager?.onBearingChanged(bearing)

// Compass
listOf<ICompassView>(
binding.roundCompass,
binding.radarCompass,
binding.linearCompass
).forEach {
it.azimuth = compass.bearing
it.azimuth = bearing
it.declination = declination
}
}

// Location
if (hasGpsUpdate) {
binding.navigationTitle.subtitle.setTextDistinct(
formatService.formatLocation(
gps.location
)
)
}
private fun updateLocation() {
val location = locationState.read()

updateNavigationButton()
binding.navigationTitle.subtitle.setTextDistinct(
formatService.formatLocation(location)
)

// show on lock screen
if (lockScreenPresence && (destination != null || destinationBearing != null)) {
activity?.let {
tryOrNothing {
Screen.setShowWhenLocked(it, true)
}
}
layerManager?.onLocationChanged(location, gps.horizontalAccuracy)

// Compass center point
listOf<ICompassView>(
binding.roundCompass,
binding.radarCompass,
binding.linearCompass
).forEach {
it.compassCenter = location
}

sightingCompass?.update()
updateNearbyBeacons()
updateDeclination()

hasGpsUpdate = false
if (!astronomyDataLoaded) {
updateAstronomyData()
}

if (useRadarCompass) {
val loadGeofence = Geofence(
location,
Distance.meters(nearbyDistance + 10)
)
val bounds = CoordinateBounds.from(loadGeofence)
layerManager?.onBoundsChanged(bounds)
}
}

private fun updateCompassLayers() {
Expand Down Expand Up @@ -719,6 +775,7 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
}

private fun getPosition(): Position {
// TODO: Remove this concept
return Position(
gps.location,
altimeter.altitude,
Expand Down Expand Up @@ -746,10 +803,9 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
}
}

private fun onOrientationUpdate(): Boolean {

private fun onOrientationUpdate() {
if (orientation.orientation == lastOrientation) {
return true
return
}

lastOrientation = orientation.orientation
Expand All @@ -768,44 +824,12 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {
} else {
disableSightingCompass()
}
return true
}

private fun onLocationUpdate() {
layerManager?.onLocationChanged(gps.location, gps.horizontalAccuracy)

// Compass center point
listOf<ICompassView>(
binding.roundCompass,
binding.radarCompass,
binding.linearCompass
).forEach {
it.compassCenter = gps.location
}

updateNearbyBeacons()
updateDeclination()

if (!astronomyDataLoaded) {
updateAstronomyData()
}

if (useRadarCompass) {
val loadGeofence = Geofence(
gps.location,
Distance.meters(nearbyDistance + 10)
)
val bounds = CoordinateBounds.from(loadGeofence)
layerManager?.onBoundsChanged(bounds)
}

hasGpsUpdate = true
}

private fun updateSensorStatus() {
inBackground {
compassStatusBadge = compassStatusBadgeProvider.getBadge()
gpsStatusBadge = gpsStatusBadgeProvider.getBadge()
compassStatusState.write(compassStatusBadgeProvider.getBadge())
gpsStatusState.write(gpsStatusBadgeProvider.getBadge())

val codes = onDefault {
diagnostics.flatMap { it.scan() }
Expand Down Expand Up @@ -835,7 +859,6 @@ class NavigatorFragment : BoundFragment<ActivityNavigatorBinding>() {

private fun updateNavigator() {
handleShowWhenLocked()
onLocationUpdate()
updateNavigationButton()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package com.kylecorry.trail_sense.shared.data

data class TrackedState<T>(val initialState: T) {
class TrackedState<T>(initialState: T) {
private var state: T = initialState
set(value) {
if (value != field) {
hasChanges = true
}
field = value
hasChanges = true
}

/**
* True if the state has changed since the last read
*/
var hasChanges = false
var hasChanges = true

/**
* Read the state
Expand All @@ -28,4 +30,11 @@ data class TrackedState<T>(val initialState: T) {
fun write(value: T) {
state = value
}

/**
* Reset the read state
*/
fun resetReadState() {
hasChanges = true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.annotation.DrawableRes
import androidx.core.view.isVisible
import com.kylecorry.andromeda.core.system.Resources
import com.kylecorry.andromeda.core.ui.Colors
import com.kylecorry.andromeda.core.ui.setTextDistinct
import com.kylecorry.trail_sense.R
import com.kylecorry.trail_sense.databinding.ViewDataPointBinding

Expand All @@ -19,13 +20,13 @@ class DataPointView(context: Context, attrs: AttributeSet?) : FrameLayout(contex
var title: String
get() = binding.dataPointTitle.text.toString()
set(value) {
binding.dataPointTitle.text = value
binding.dataPointTitle.setTextDistinct(value)
}

var description: String
get() = binding.dataPointDesc.text.toString()
set(value) {
binding.dataPointDesc.text = value
binding.dataPointDesc.setTextDistinct(value)
}

init {
Expand Down

0 comments on commit 77c2a8e

Please sign in to comment.