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:
commit
3a0720dd1f
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue