Skip to content

Commit 7b1445d

Browse files
authored
Merge pull request #1194 from CruGlobal/viewModelObserveOnce
GT-1497 add observeOnce variation that is linked to the ViewModel lifecycle
2 parents 06a4b32 + a1d3224 commit 7b1445d

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

gto-support-androidx-lifecycle/src/main/kotlin/org/ccci/gto/android/common/androidx/lifecycle/LiveData+ViewModel.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.ccci.gto.android.common.androidx.lifecycle
22

3+
import androidx.annotation.MainThread
34
import androidx.lifecycle.LiveData
45
import androidx.lifecycle.Observer
56
import androidx.lifecycle.ViewModel
@@ -47,3 +48,7 @@ fun <IN1, IN2, IN3> ViewModel.observe(
4748
observer(source1.value as IN1, source2.value as IN2, source3.value as IN3)
4849
}
4950
// endregion Multi-observe
51+
52+
@MainThread
53+
inline fun <T> LiveData<T>.observeOnce(viewModel: ViewModel, crossinline onChanged: (T) -> Unit) =
54+
observeOnceObserver(onChanged).also { observe(viewModel, it) }

gto-support-androidx-lifecycle/src/test/kotlin/org/ccci/gto/android/common/androidx/lifecycle/LiveDataViewModelObserverTest.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import org.junit.Before
99
import org.junit.Test
1010
import org.mockito.kotlin.any
1111
import org.mockito.kotlin.argumentCaptor
12+
import org.mockito.kotlin.eq
13+
import org.mockito.kotlin.mock
14+
import org.mockito.kotlin.never
1215
import org.mockito.kotlin.times
1316
import org.mockito.kotlin.verify
1417
import org.mockito.kotlin.verifyNoMoreInteractions
@@ -84,4 +87,36 @@ class LiveDataViewModelObserverTest : BaseLiveDataTest() {
8487
}
8588
}
8689
// endregion Multi-observe
90+
91+
// region observeOnce
92+
@Test
93+
fun `observeOnce() - Only Called One Time`() {
94+
// observe before LiveData has data
95+
val observer: (Int) -> Unit = mock()
96+
liveData.observeOnce(viewModel, observer)
97+
verify(observer, never()).invoke(any())
98+
liveData.value = 1
99+
verify(observer).invoke(eq(1))
100+
liveData.value = 2
101+
verifyNoMoreInteractions(observer)
102+
103+
// observe after LiveData has data
104+
val observer2: (Int) -> Unit = mock()
105+
liveData.observeOnce(viewModel, observer2)
106+
verify(observer2).invoke(eq(2))
107+
liveData.value = 3
108+
verifyNoMoreInteractions(observer2)
109+
}
110+
111+
@Test
112+
fun `observeOnce() - Respects ViewModel clear`() {
113+
val observer: (Int) -> Unit = mock()
114+
liveData.observeOnce(viewModel, observer)
115+
116+
// Lifecycle is destroyed so observer is removed before it can be called
117+
viewModel.clear()
118+
liveData.value = 1
119+
verify(observer, never()).invoke(any())
120+
}
121+
// endregion observeOnce
87122
}

0 commit comments

Comments
 (0)