Explorar el Código

Attempt to move the unzip coroutine to a ViewModel

PabloG02 hace 3 años
padre
commit
3733187c14

+ 38 - 2
src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/IndeterminateProgressDialogFragment.kt

@@ -2,33 +2,69 @@ package org.yuzu.yuzu_emu.fragments
 
 
 import android.app.Dialog
 import android.app.Dialog
 import android.os.Bundle
 import android.os.Bundle
+import android.widget.Toast
 import androidx.fragment.app.DialogFragment
 import androidx.fragment.app.DialogFragment
+import androidx.lifecycle.ViewModelProvider
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
 import org.yuzu.yuzu_emu.databinding.DialogProgressBarBinding
+import org.yuzu.yuzu_emu.model.TaskViewModel
+import java.io.Serializable
+
 
 
 class IndeterminateProgressDialogFragment : DialogFragment() {
 class IndeterminateProgressDialogFragment : DialogFragment() {
+    private lateinit var taskViewModel: TaskViewModel
+
     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
     override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+        taskViewModel = ViewModelProvider(requireActivity())[TaskViewModel::class.java]
+
         val titleId = requireArguments().getInt(TITLE)
         val titleId = requireArguments().getInt(TITLE)
 
 
         val progressBinding = DialogProgressBarBinding.inflate(layoutInflater)
         val progressBinding = DialogProgressBarBinding.inflate(layoutInflater)
         progressBinding.progressBar.isIndeterminate = true
         progressBinding.progressBar.isIndeterminate = true
-        return MaterialAlertDialogBuilder(requireContext())
+        val dialog = MaterialAlertDialogBuilder(requireContext())
             .setTitle(titleId)
             .setTitle(titleId)
             .setView(progressBinding.root)
             .setView(progressBinding.root)
-            .show()
+            .create()
+        dialog.setCanceledOnTouchOutside(false)
+
+        taskViewModel.isComplete.observe(this) { complete ->
+            if (complete) {
+                dialog.dismiss()
+                when (val result = taskViewModel.result.value) {
+                    is String -> Toast.makeText(requireContext(), result, Toast.LENGTH_LONG).show()
+                    is MessageDialogFragment -> result.show(
+                        parentFragmentManager,
+                        MessageDialogFragment.TAG
+                    )
+                }
+                taskViewModel.clear()
+            }
+        }
+
+        if (taskViewModel.isRunning.value == false) {
+            val task = requireArguments().getSerializable(TASK) as? () -> Any
+            if (task != null) {
+                taskViewModel.task = task
+                taskViewModel.runTask()
+            }
+        }
+        return dialog
     }
     }
 
 
     companion object {
     companion object {
         const val TAG = "IndeterminateProgressDialogFragment"
         const val TAG = "IndeterminateProgressDialogFragment"
 
 
         private const val TITLE = "Title"
         private const val TITLE = "Title"
+        private const val TASK = "Task"
 
 
         fun newInstance(
         fun newInstance(
             titleId: Int,
             titleId: Int,
+            task: () -> Any
         ): IndeterminateProgressDialogFragment {
         ): IndeterminateProgressDialogFragment {
             val dialog = IndeterminateProgressDialogFragment()
             val dialog = IndeterminateProgressDialogFragment()
             val args = Bundle()
             val args = Bundle()
             args.putInt(TITLE, titleId)
             args.putInt(TITLE, titleId)
+            args.putSerializable(TASK, task as Serializable)
             dialog.arguments = args
             dialog.arguments = args
             return dialog
             return dialog
         }
         }

+ 42 - 0
src/android/app/src/main/java/org/yuzu/yuzu_emu/model/TaskViewModel.kt

@@ -0,0 +1,42 @@
+package org.yuzu.yuzu_emu.model
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+
+class TaskViewModel : ViewModel() {
+    private val _result = MutableLiveData<Any>()
+    val result: LiveData<Any> = _result
+
+    private val _isComplete = MutableLiveData<Boolean>()
+    val isComplete: LiveData<Boolean> = _isComplete
+
+    private val _isRunning = MutableLiveData<Boolean>()
+    val isRunning: LiveData<Boolean> = _isRunning
+
+    lateinit var task: () -> Any
+
+    init {
+        clear()
+    }
+
+    fun clear() {
+        _result.value = Any()
+        _isComplete.value = false
+        _isRunning.value = false
+    }
+
+    fun runTask() {
+        if (_isRunning.value == true) return
+        _isRunning.value = true
+
+        viewModelScope.launch(Dispatchers.IO) {
+            val res = task()
+            _result.postValue(res)
+            _isComplete.postValue(true)
+        }
+    }
+}

+ 14 - 25
src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt

@@ -26,7 +26,6 @@ import androidx.preference.PreferenceManager
 import com.google.android.material.color.MaterialColors
 import com.google.android.material.color.MaterialColors
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import com.google.android.material.navigation.NavigationBarView
 import com.google.android.material.navigation.NavigationBarView
-import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import kotlinx.coroutines.withContext
@@ -340,44 +339,34 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
                 File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/")
                 File(DirectoryInitialization.userDirectory + "/nand/system/Contents/registered/")
             val cacheFirmwareDir = File("${cacheDir.path}/registered/")
             val cacheFirmwareDir = File("${cacheDir.path}/registered/")
 
 
-            val installingFirmwareDialog = IndeterminateProgressDialogFragment.newInstance(
-                R.string.firmware_installing
-            )
-            installingFirmwareDialog.isCancelable = false
-            installingFirmwareDialog.show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
-
-            lifecycleScope.launch(Dispatchers.IO) {
+            val task: () -> Any = {
+                var messageToShow: Any
                 try {
                 try {
                     FileUtil.unzip(inputZip, cacheFirmwareDir)
                     FileUtil.unzip(inputZip, cacheFirmwareDir)
                     val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1
                     val unfilteredNumOfFiles = cacheFirmwareDir.list()?.size ?: -1
                     val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2
                     val filteredNumOfFiles = cacheFirmwareDir.list(filterNCA)?.size ?: -2
                     if (unfilteredNumOfFiles != filteredNumOfFiles) {
                     if (unfilteredNumOfFiles != filteredNumOfFiles) {
-                        withContext(Dispatchers.Main) {
-                            installingFirmwareDialog.dismiss()
-                            MessageDialogFragment.newInstance(
-                                R.string.firmware_installed_failure,
-                                R.string.firmware_installed_failure_description
-                            ).show(supportFragmentManager, MessageDialogFragment.TAG)
-                        }
+                        messageToShow = MessageDialogFragment.newInstance(
+                            R.string.firmware_installed_failure,
+                            R.string.firmware_installed_failure_description
+                        )
                     } else {
                     } else {
                         firmwarePath.deleteRecursively()
                         firmwarePath.deleteRecursively()
                         cacheFirmwareDir.copyRecursively(firmwarePath, true)
                         cacheFirmwareDir.copyRecursively(firmwarePath, true)
-                        withContext(Dispatchers.Main) {
-                            installingFirmwareDialog.dismiss()
-                            Toast.makeText(
-                                applicationContext,
-                                getString(R.string.save_file_imported_success),
-                                Toast.LENGTH_LONG
-                            ).show()
-                        }
+                        messageToShow = getString(R.string.save_file_imported_success)
                     }
                     }
                 } catch (e: Exception) {
                 } catch (e: Exception) {
-                    Toast.makeText(applicationContext, getString(R.string.fatal_error), Toast.LENGTH_LONG)
-                        .show()
+                    messageToShow = getString(R.string.fatal_error)
                 } finally {
                 } finally {
                     cacheFirmwareDir.deleteRecursively()
                     cacheFirmwareDir.deleteRecursively()
                 }
                 }
+                messageToShow
             }
             }
+
+            IndeterminateProgressDialogFragment.newInstance(
+                R.string.firmware_installing,
+                task
+            ).show(supportFragmentManager, IndeterminateProgressDialogFragment.TAG)
         }
         }
 
 
     val getAmiiboKey =
     val getAmiiboKey =