Merge pull request #12681 from nlebeck/taskviewmodel-refactor

Refactor `TaskViewModel` to track task-related state in a single `MutableLiveData` instance
This commit is contained in:
Admiral H. Curtiss 2024-04-13 01:42:12 +02:00 committed by GitHub
commit 3a0720dd1f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 47 additions and 34 deletions

View File

@ -102,10 +102,7 @@ class UserDataActivity : AppCompatActivity() {
dialog.show(supportFragmentManager, UserDataImportWarningDialog.TAG)
} else if (requestCode == REQUEST_CODE_EXPORT && resultCode == RESULT_OK) {
taskViewModel.clear()
taskViewModel.task = {
val resultResource = exportUserData(data!!.data!!)
taskViewModel.setResult(resultResource)
}
taskViewModel.task = { exportUserData(data!!.data!!) }
val arguments = Bundle()
arguments.putInt(TaskDialog.KEY_TITLE, R.string.export_in_progress)

View File

@ -34,14 +34,11 @@ class TaskDialog : DialogFragment() {
val progressMessage = requireArguments().getInt(KEY_MESSAGE)
if (progressMessage != 0) dialog.setMessage(resources.getString(progressMessage))
viewModel.isComplete.observe(this) { complete: Boolean ->
if (complete && viewModel.result.value != null) {
viewModel.result.observe(this) { result: Int? ->
if (result != null) {
dialog.dismiss()
val notificationArguments = Bundle()
notificationArguments.putInt(
TaskCompleteDialog.KEY_MESSAGE,
viewModel.result.value!!
)
notificationArguments.putInt(TaskCompleteDialog.KEY_MESSAGE, result)
val taskCompleteDialog = TaskCompleteDialog()
taskCompleteDialog.arguments = notificationArguments

View File

@ -32,11 +32,9 @@ class UserDataImportWarningDialog : DialogFragment() {
taskArguments.putBoolean(TaskDialog.KEY_CANCELLABLE, false)
taskViewModel.task = {
taskViewModel.setResult(
(requireActivity() as UserDataActivity).importUserData(
requireArguments().getString(KEY_URI_RESULT)!!.toUri()
)
)
}
taskViewModel.onResultDismiss = {

View File

@ -5,23 +5,49 @@ package org.dolphinemu.dolphinemu.model
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.map
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*
/**
* A [ViewModel] associated with a task that runs on [Dispatchers.IO] and yields an integer result.
*/
class TaskViewModel : ViewModel() {
/** Represents the execution state of the task associated with this [TaskViewModel]. */
private interface State {
/** Returns true if the task has started running and false otherwise. */
fun hasStarted() : Boolean
/** Returns the task's result if it has completed or null otherwise. */
fun result() : Int?
}
private class NotStartedState : State {
override fun hasStarted() : Boolean { return false; }
override fun result() : Int? { return null; }
}
private class RunningState : State {
override fun hasStarted() : Boolean { return true; }
override fun result() : Int? { return null; }
}
private class CompletedState(private val result: Int) : State {
override fun hasStarted() : Boolean { return true; }
override fun result() : Int { return result; }
}
var cancelled = false
var mustRestartApp = false
private val _result = MutableLiveData<Int>()
val result: LiveData<Int> get() = _result
private val state = MutableLiveData<State>(NotStartedState())
private val _isComplete = MutableLiveData<Boolean>()
val isComplete: LiveData<Boolean> get() = _isComplete
/** Yields the result of [task] if it has completed or null otherwise. */
val result: LiveData<Int?> get() = state.map {
state -> state.result()
}
private val _isRunning = MutableLiveData<Boolean>()
val isRunning: LiveData<Boolean> get() = _isRunning
lateinit var task: () -> Unit
lateinit var task: () -> Int
var onResultDismiss: (() -> Unit)? = null
init {
@ -29,28 +55,23 @@ class TaskViewModel : ViewModel() {
}
fun clear() {
_result.value = 0
_isComplete.value = false
state.value = NotStartedState()
cancelled = false
mustRestartApp = false
onResultDismiss = null
_isRunning.value = false
}
fun runTask() {
if (isRunning.value == true) return
_isRunning.value = true
if (state.value!!.hasStarted()) {
return
}
state.value = RunningState()
viewModelScope.launch {
withContext(Dispatchers.IO) {
task.invoke()
_isRunning.postValue(false)
_isComplete.postValue(true)
val result = task.invoke()
state.postValue(CompletedState(result))
}
}
}
fun setResult(result: Int) {
_result.postValue(result)
}
}