feat: remove observer when ViewModel is cleared

This commit is contained in:
Canny 2022-10-07 19:17:23 +03:00
parent 05ddbd90da
commit 477ec3e182
No known key found for this signature in database
GPG Key ID: 395CCB0AA979F27B
3 changed files with 27 additions and 26 deletions

View File

@ -149,7 +149,7 @@ class PatcherWorker(context: Context, parameters: WorkerParameters, private val
Logging.log += "Merging integrations\n" Logging.log += "Merging integrations\n"
patcher.addFiles(listOf(integrations)) {} patcher.addFiles(listOf(integrations)) {}
Logging.log += "Applying ${patches.size} patch(es)" Logging.log += "Applying ${patches.size} patch(es)\n"
patcher.executePatches().forEach { (patch, result) -> patcher.executePatches().forEach { (patch, result) ->
if (result.isFailure) { if (result.isFailure) {

View File

@ -11,6 +11,7 @@ import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Done import androidx.compose.material.icons.filled.Done
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
@ -30,7 +31,7 @@ fun PatchingScreen(
navigator: BackstackNavigator<AppDestination>, navigator: BackstackNavigator<AppDestination>,
vm: PatchingScreenViewModel = getViewModel() vm: PatchingScreenViewModel = getViewModel()
) { ) {
var patching by mutableStateOf(false) var patching by rememberSaveable {mutableStateOf(false)}
val scrollState = rememberScrollState() val scrollState = rememberScrollState()
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
LaunchedEffect(patching) { LaunchedEffect(patching) {
@ -96,6 +97,7 @@ fun PatchingScreen(
) )
Text(text = "Completed!", fontSize = 30.sp) Text(text = "Completed!", fontSize = 30.sp)
} }
PatchingScreenViewModel.Status.Idle -> {}
} }
} }
} }

View File

@ -1,59 +1,58 @@
package app.revanced.manager.ui.viewmodel package app.revanced.manager.ui.viewmodel
import android.app.Application import android.app.Application
import android.util.Log
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.work.* import androidx.work.*
import app.revanced.manager.patcher.worker.PatcherWorker import app.revanced.manager.patcher.worker.PatcherWorker
import app.revanced.manager.util.tag
class PatchingScreenViewModel(val app: Application) : ViewModel() { class PatchingScreenViewModel(val app: Application) : ViewModel() {
// create worker private val patcherWorker = OneTimeWorkRequest.Builder(PatcherWorker::class.java) // create Worker
private val patcherWorker = OneTimeWorkRequest.Builder(PatcherWorker::class.java)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.setInputData( .setInputData(
Data.Builder() Data.Builder()
.build() .build()
).build() ).build()
var status by mutableStateOf<Status>(Status.Patching) private val liveData = WorkManager.getInstance(app).getWorkInfoByIdLiveData(patcherWorker.id) // get LiveData
private val observer = Observer { workInfo: WorkInfo -> // observer for observing patch status
status = when (workInfo.state) {
WorkInfo.State.RUNNING -> Status.Patching
WorkInfo.State.SUCCEEDED -> Status.Success
WorkInfo.State.FAILED -> Status.Failure
else -> Status.Idle
}
}
var status by mutableStateOf<Status>(Status.Idle)
sealed class Status { sealed class Status {
object Idle : Status()
object Patching : Status() object Patching : Status()
object Success : Status() object Success : Status()
object Failure : Status() object Failure : Status()
} }
fun startPatcher() { fun startPatcher() {
cancelPatching() // cancel existing patching process cancelPatching() // cancel patching if its still running
Logging.log = "" // and clear logs
WorkManager.getInstance(app) WorkManager.getInstance(app)
.enqueueUniqueWork("patching", ExistingWorkPolicy.KEEP, patcherWorker) .enqueueUniqueWork("patching", ExistingWorkPolicy.KEEP, patcherWorker) // enqueue patching process
status = Status.Patching // set status liveData.observeForever(observer) // start observing patch status
Log.d(tag, "Created worker.")
val liveData = WorkManager.getInstance(app).getWorkInfoByIdLiveData(patcherWorker.id) // live data for observing
liveData.observeForever { workInfo: WorkInfo -> // shitty solution but it works
status = when (workInfo.state) {
WorkInfo.State.SUCCEEDED -> Status.Success
WorkInfo.State.FAILED -> Status.Failure
else -> Status.Patching
}
}
Log.d(tag, "Worker finished.")
} }
private fun cancelPatching() { private fun cancelPatching() {
WorkManager.getInstance(app).cancelWorkById(patcherWorker.id) WorkManager.getInstance(app).cancelWorkById(patcherWorker.id)
} }
override fun onCleared() {
super.onCleared()
liveData.removeObserver(observer) // remove observer when ViewModel is destroyed
}
} }
object Logging { object Logging {