mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-13 17:07:40 +00:00
fix(android): Wear Talk works after exiting and reopening (#112383)
* fix(android): scope Wear Talk client to ViewModel * test(android): exercise Wear ViewModel factory lifecycle Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com> --------- Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -31,10 +31,6 @@ class WearApplication : Application() {
|
||||
WearGatewayRepository(proxyClient)
|
||||
}
|
||||
|
||||
internal val realtimeTalkClient: WearRealtimeTalkClient by lazy {
|
||||
WearRealtimeTalkClient(this, gatewayRepository)
|
||||
}
|
||||
|
||||
private val visibleActivities = VisibleActivityTracker()
|
||||
|
||||
internal fun onActivityStarted() = visibleActivities.onStarted()
|
||||
|
||||
@@ -176,7 +176,7 @@ internal class WearViewModel(
|
||||
) : AndroidViewModel(application) {
|
||||
private val app = application as WearApplication
|
||||
private val repository = app.gatewayRepository
|
||||
private val realtimeTalkClient = app.realtimeTalkClient
|
||||
private val realtimeTalkClient = WearRealtimeTalkClient(app, repository)
|
||||
private val mutableState = MutableStateFlow(WearUiState())
|
||||
private val eventSequenceTracker = WearEventSequenceTracker()
|
||||
private val eventSourceTracker = WearEventSourceTracker()
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package ai.openclaw.wear
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.ViewModelStore
|
||||
import androidx.lifecycle.ViewModelStoreOwner
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotSame
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.RuntimeEnvironment
|
||||
import org.robolectric.annotation.Config
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(application = WearApplication::class, sdk = [35])
|
||||
class WearViewModelLifecycleTest {
|
||||
@Test
|
||||
fun recreatedViewModelGetsALiveTalkClientAfterThePreviousOneClears() {
|
||||
val app = RuntimeEnvironment.getApplication() as WearApplication
|
||||
val factory = ViewModelProvider.AndroidViewModelFactory.getInstance(app)
|
||||
val firstOwner = TestViewModelStoreOwner()
|
||||
val firstViewModel = ViewModelProvider(firstOwner, factory)[WearViewModel::class.java]
|
||||
val firstClient = firstViewModel.realtimeTalkClientForTest()
|
||||
|
||||
firstOwner.viewModelStore.clear()
|
||||
|
||||
val reopenedOwner = TestViewModelStoreOwner()
|
||||
val reopenedViewModel = ViewModelProvider(reopenedOwner, factory)[WearViewModel::class.java]
|
||||
val reopenedClient = reopenedViewModel.realtimeTalkClientForTest()
|
||||
try {
|
||||
assertFalse(firstClient.scopeForTest().coroutineContext[Job]?.isActive == true)
|
||||
assertNotSame(firstClient, reopenedClient)
|
||||
assertTrue(reopenedClient.scopeForTest().coroutineContext[Job]?.isActive == true)
|
||||
} finally {
|
||||
reopenedOwner.viewModelStore.clear()
|
||||
}
|
||||
}
|
||||
|
||||
private class TestViewModelStoreOwner : ViewModelStoreOwner {
|
||||
override val viewModelStore = ViewModelStore()
|
||||
}
|
||||
|
||||
private fun WearViewModel.realtimeTalkClientForTest(): WearRealtimeTalkClient =
|
||||
javaClass.getDeclaredField("realtimeTalkClient").run {
|
||||
isAccessible = true
|
||||
get(this@realtimeTalkClientForTest) as WearRealtimeTalkClient
|
||||
}
|
||||
|
||||
private fun WearRealtimeTalkClient.scopeForTest(): CoroutineScope =
|
||||
javaClass.getDeclaredField("scope").run {
|
||||
isAccessible = true
|
||||
get(this@scopeForTest) as CoroutineScope
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user