-
Notifications
You must be signed in to change notification settings - Fork 17
/
AndroidViewModelSampleScreen.kt
120 lines (105 loc) · 4.34 KB
/
AndroidViewModelSampleScreen.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package com.github.terrakok.modo.sample.screens.viewmodel
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.createSavedStateHandle
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import com.github.terrakok.modo.ExperimentalModoApi
import com.github.terrakok.modo.Screen
import com.github.terrakok.modo.ScreenKey
import com.github.terrakok.modo.generateScreenKey
import com.github.terrakok.modo.lifecycle.LifecycleScreenEffect
import com.github.terrakok.modo.sample.screens.MainScreenContent
import com.github.terrakok.modo.sample.screens.base.COUNTER_DELAY_MS
import com.github.terrakok.modo.stack.LocalStackNavigation
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import logcat.logcat
@Parcelize
internal class AndroidViewModelSampleScreen(
private val screenPos: Int,
override val screenKey: ScreenKey = generateScreenKey()
) : Screen {
@OptIn(ExperimentalModoApi::class)
@Composable
override fun Content(modifier: Modifier) {
// val lifecycleOwner = LocalLifecycleOwner.current
// You will lose onResume, onStop, if you use regular DisposableEffect or LaunchedEffect, because it finishes as soon it leaves composition.
// DisposableEffect(lifecycleOwner) {
// val observer = LifecycleEventObserver { _, event ->
// logcat { "AndroidViewModelSampleScreen DisposableEffect $screenKey: event $event" }
// }
// lifecycleOwner.lifecycle.addObserver(observer)
// onDispose {
// lifecycleOwner.lifecycle.removeObserver(observer)
// }
// }
// Coroutines way
// LaunchedScreenEffect {
// lifecycleOwner.lifecycle.eventFlow.collect { lifecycleState ->
// logcat { "AndroidViewModelSampleScreen $screenKey: LifecycleState $lifecycleState" }
// }
// }
// Disposable observer way
// DisposableScreenEffect {
// logcat { "AndroidViewModelSampleScreen $screenPos DisposableScreenEffect created" }
// val observer = object : LifecycleEventObserver {
// override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
// logcat { "AndroidViewModelSampleScreen $screenKey observer: Lifecycle.Event $event" }
// }
// }
// lifecycleOwner.lifecycle.addObserver(observer)
// onDispose {
// logcat { "AndroidViewModelSampleScreen $screenKey DisposableScreenEffect disposed" }
// lifecycleOwner.lifecycle.removeObserver(observer)
// }
// }
LifecycleScreenEffect {
object : LifecycleEventObserver {
override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
logcat { "AndroidViewModelSampleScreen $screenKey: Lifecycle.Event $event" }
}
}
}
val viewModel: SampleViewModel = viewModel {
SampleViewModel(screenPos, createSavedStateHandle())
}
MainScreenContent(screenPos, screenKey, viewModel.stateFlow.collectAsState().value, LocalStackNavigation.current, modifier)
}
}
internal class SampleViewModel(
private val screenPos: Int,
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
val stateFlow: StateFlow<Int> = savedStateHandle.getStateFlow(STATE_KEY, 0)
private var state: Int
get() = stateFlow.value
set(value) {
savedStateHandle[STATE_KEY] = value
}
init {
logcat { "SampleViewModel init $screenPos" }
viewModelScope.launch {
while (isActive) {
delay(COUNTER_DELAY_MS)
state += 1
}
}
}
override fun onCleared() {
logcat { "SampleViewModel onCleared $screenPos" }
super.onCleared()
}
companion object {
private const val STATE_KEY = "STATE_KEY"
}
}