class CountdownViewModel : ViewModel() {
private val totalTimeSeconds = 15 * 60 // 15 minutes in seconds
private var remainingTime = totalTimeSeconds
private val _time = MutableStateFlow(formatTime(remainingTime))
val time: StateFlow<String> = _time.asStateFlow()
private val _progress = MutableStateFlow(1f)
val progress: StateFlow<Float> = _progress.asStateFlow()
private val _isRunning = MutableStateFlow(false)
val isRunning: StateFlow<Boolean> = _isRunning.asStateFlow()
fun startTimer() {
if (isRunning.value) return
_isRunning.value = true
viewModelScope.launch {
while (remainingTime > 0 && isRunning.value) {
delay(1000)
remainingTime--
_time.value = formatTime(remainingTime)
_progress.value = remainingTime / totalTimeSeconds.toFloat()
}
_isRunning.value = false
}
}
fun toggleTimer() {
if (isRunning.value) stopTimer() else startTimer()
}
fun stopTimer() {
_isRunning.value = false
remainingTime = totalTimeSeconds
_time.value = formatTime(remainingTime)
_progress.value = 1f
}
private fun formatTime(seconds: Int): String {
val minutes = seconds / 60
val secs = seconds % 60
return "%02d:%02d".format(minutes, secs)
}
}
class CountdownViewModel: ObservableObject {
private let totalTimeSeconds = 10 * 60 // 10 minutes in seconds
private var remainingTime: Int
private var timer: Timer?
u/Published var time: String
@Published var progress: Float
@Published var isRunning: Bool
init() {
self.remainingTime = totalTimeSeconds
self.time = CountdownViewModel.formatTime(totalTimeSeconds)
self.progress = 1.0
self.isRunning = false
}
func startTimer() {
if isRunning { return }
isRunning = true
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
guard let self = self else { return }
if self.remainingTime > 0 {
self.remainingTime -= 1
self.time = CountdownViewModel.formatTime(self.remainingTime)
self.progress = Float(self.remainingTime) / Float(self.totalTimeSeconds)
} else {
self.stopTimer()
}
}
}
func toggleTimer() {
if isRunning {
stopTimer()
} else {
startTimer()
}
}
func stopTimer() {
isRunning = false
timer?.invalidate()
timer = nil
remainingTime = totalTimeSeconds
time = CountdownViewModel.formatTime(remainingTime)
progress = 1.0
}
private static func formatTime(_ seconds: Int) -> String {
let minutes = seconds / 60
let secs = seconds % 60
return String(format: "%02d:%02d", minutes, secs)
}
}
class MainActivity : ComponentActivity() {
private val viewModel by viewModels<CountdownViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val progress by viewModel.progress.collectAsStateWithLifecycle(initialValue = 0f)
val time by viewModel.time.collectAsStateWithLifecycle()
val isRunning by viewModel.isRunning.collectAsStateWithLifecycle()
App(
onButtonClicked = {
viewModel.toggleTimer()
},
progress = progress,
time = time,
isRunning = isRunning
)
}
}
}
MainViewController.kt
fun FullMainViewController(
time: String,
progress: Float,
isRunning: Boolean,
toggleTimer: () -> Unit
) = ComposeUIViewController {
App(
onButtonClicked = toggleTimer,
progress = progress,
time = time,
isRunning = isRunning
)
}
ContentView.swift
struct ComposeView: UIViewControllerRepresentable {
@ObservedObject var viewModel: CountdownViewModel
func makeUIViewController(context: Context) -> UIViewController {
return MainViewControllerKt.FullMainViewController(
time: viewModel.time,
progress: viewModel.progress,
isRunning: viewModel.isRunning,
toggleTimer: { viewModel.toggleTimer() }
)
}
func updateUIViewController(
_ uiViewController: UIViewController,
context: Context
) {}
}
struct ContentView: View {
@StateObject private var viewModel = CountdownViewModel()
var body: some View {
ComposeView(
viewModel: viewModel
)
.ignoresSafeArea(.keyboard) // Compose has own keyboard handler
}
}
问题
Android应用程序运行良好,但我无法找到一种使iOS上的合并更新的方法。我的意思是,我可以在ComposeView中添加一个
.id(viewModel.time)
,以便每次都被调用,但性能看起来很糟糕。还有其他方法可以从iOS中更新合并吗?
notes我知道你们中的一些人可能建议通过Kotlin共享相同的ViewModel,但我想避免这种情况。我正在考虑创建一个仅解决UI的解决方案,我希望能够将其作为UI库将其导入到Android和iOS中。
Https://developer.android.com/topic/architecture#recommend--app-arch-)。
数据层
makeUIViewController
expect fun createTimer(): Timer