diff --git a/androidshared/src/main/java/org/odk/collect/androidshared/livedata/LiveDataUtils.java b/androidshared/src/main/java/org/odk/collect/androidshared/livedata/LiveDataUtils.java index d83966e179c..dfd3bec1e8e 100644 --- a/androidshared/src/main/java/org/odk/collect/androidshared/livedata/LiveDataUtils.java +++ b/androidshared/src/main/java/org/odk/collect/androidshared/livedata/LiveDataUtils.java @@ -62,6 +62,7 @@ private static class CombinedLiveData extends MediatorLiveData { private final Object[] values; private final Function map; + private T lastEmitted; CombinedLiveData(LiveData[] sources, Function map) { this.map = map; @@ -79,7 +80,12 @@ private static class CombinedLiveData extends MediatorLiveData { } private void update() { - setValue(map.apply(values)); + T newValue = map.apply(values); + + if (lastEmitted == null || !lastEmitted.equals(newValue)) { + lastEmitted = newValue; + setValue(newValue); + } } } diff --git a/androidshared/src/test/java/org/odk/collect/androidshared/livedata/LiveDataUtilsTest.kt b/androidshared/src/test/java/org/odk/collect/androidshared/livedata/LiveDataUtilsTest.kt index c981cdbde4d..56cb1f00e12 100644 --- a/androidshared/src/test/java/org/odk/collect/androidshared/livedata/LiveDataUtilsTest.kt +++ b/androidshared/src/test/java/org/odk/collect/androidshared/livedata/LiveDataUtilsTest.kt @@ -34,4 +34,19 @@ class LiveDataUtilsTest { assertThat(combined.getOrAwaitValue(), equalTo(Pair("one-updated", "two"))) } + + @Test + fun `#combine skips emission when result is equal to previous`() { + val one = MutableLiveData("one") + val combined = one.combine(MutableLiveData()) + + var counter = 0 + LiveDataUtils.observe(combined) { + counter++ + } + + one.value = "one" + + assertThat(counter, equalTo(1)) + } } diff --git a/geo/src/main/java/org/odk/collect/geo/geopoly/GeoPolyFragment.kt b/geo/src/main/java/org/odk/collect/geo/geopoly/GeoPolyFragment.kt index f55062f3dfe..abde9cec3d8 100644 --- a/geo/src/main/java/org/odk/collect/geo/geopoly/GeoPolyFragment.kt +++ b/geo/src/main/java/org/odk/collect/geo/geopoly/GeoPolyFragment.kt @@ -15,7 +15,6 @@ import androidx.lifecycle.asLiveData import androidx.lifecycle.viewmodel.viewModelFactory import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar -import org.odk.collect.androidshared.livedata.LiveDataExt.combine import org.odk.collect.androidshared.ui.DialogFragmentUtils.showIfNotShowing import org.odk.collect.androidshared.ui.FragmentFactoryBuilder import org.odk.collect.androidshared.ui.SnackbarUtils @@ -253,8 +252,7 @@ class GeoPolyFragment @JvmOverloads constructor( }, displayDismissButton = true ) - val viewData = viewModel.points.asLiveData().combine(viewModel.invalidMessage) - viewData.observe(viewLifecycleOwner) { (points, invalidMessage) -> + viewModel.viewData.observe(viewLifecycleOwner) { (points, invalidMessage) -> val isValid = invalidMessage == null if (!isValid) { snackbar.setText(invalidMessage) diff --git a/geo/src/main/java/org/odk/collect/geo/geopoly/GeoPolyViewModel.kt b/geo/src/main/java/org/odk/collect/geo/geopoly/GeoPolyViewModel.kt index b8d01102d19..0e887962cb4 100644 --- a/geo/src/main/java/org/odk/collect/geo/geopoly/GeoPolyViewModel.kt +++ b/geo/src/main/java/org/odk/collect/geo/geopoly/GeoPolyViewModel.kt @@ -2,10 +2,12 @@ package org.odk.collect.geo.geopoly import androidx.lifecycle.LiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.asLiveData import androidx.lifecycle.map import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import org.odk.collect.androidshared.data.Consumable +import org.odk.collect.androidshared.livedata.LiveDataExt.combine import org.odk.collect.androidshared.livedata.LiveDataExt.withLast import org.odk.collect.async.Cancellable import org.odk.collect.async.Scheduler @@ -53,6 +55,8 @@ class GeoPolyViewModel( } } + val viewData = _points.asLiveData().combine(invalidMessage) + private var accuracyThreshold: Int = 0 private var recording: Cancellable? = null diff --git a/geo/src/test/java/org/odk/collect/geo/geopoly/GeoPolyViewModelTest.kt b/geo/src/test/java/org/odk/collect/geo/geopoly/GeoPolyViewModelTest.kt index c0f19c974b8..1fdeb510b89 100644 --- a/geo/src/test/java/org/odk/collect/geo/geopoly/GeoPolyViewModelTest.kt +++ b/geo/src/test/java/org/odk/collect/geo/geopoly/GeoPolyViewModelTest.kt @@ -7,6 +7,7 @@ import org.hamcrest.Matchers.equalTo import org.junit.Rule import org.junit.Test import org.mockito.Mockito.mock +import org.odk.collect.androidtest.MainDispatcherRule import org.odk.collect.testshared.getOrAwaitValue class GeoPolyViewModelTest { @@ -14,6 +15,9 @@ class GeoPolyViewModelTest { @get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule() + @get:Rule + val mainDispatcherRule = MainDispatcherRule() + @Test fun `#fixedAlerts is null until after invalid message is non-null`() { val invalidMessage = MutableLiveData(null) diff --git a/google-maps/src/main/java/org/odk/collect/googlemaps/GoogleMapFragment.java b/google-maps/src/main/java/org/odk/collect/googlemaps/GoogleMapFragment.java index 61e6a9cb179..96f291b8c6a 100644 --- a/google-maps/src/main/java/org/odk/collect/googlemaps/GoogleMapFragment.java +++ b/google-maps/src/main/java/org/odk/collect/googlemaps/GoogleMapFragment.java @@ -850,6 +850,7 @@ public void dispose() { private void clearPolyline() { if (polyline != null) { + polyline.setVisible(false); polyline.remove(); polyline = null; } @@ -1024,6 +1025,7 @@ public List getPoints() { private void clearPolygon() { if (polygon != null) { + polygon.setVisible(false); polygon.remove(); polygon = null; }