Prevent parallel loading and fix duplicate ViewModel state collection in FiltersActivity (#4472)
This pull request fixes the following issues: - `FiltersActivity` launches a new coroutine to collect the ViewModel state every time the Activity is resumed, without cancelling the previous coroutine. - `FiltersActivity` reloads the filters in `onResume()`, even if loading is already in progress (without cancelling the current loading). This can lead to inconsistent state. List of improvements: - Implement `launchAndRepeatOnLifecycle()` to combine `coroutineScope.launch()` with `repeatOnLifecycle()` for the same `Lifecycle`. Use it in `FiltersActivity` to update the view only when the Activity is visible. - Optimize the filters loading: load them when `FiltersViewModel` is created and when returning from `EditFilterActivity` (when receiving the Activity result). Cancel the load already in progress, if any. - use `MutableStateFlow.update()` to update the state in a thread-safe way. - Turn `FiltersViewModel.deleteFilter()` into a suspending function in order to perform the update in the coroutinescope of the Activity lifecycle, so the View passed as argument doesn't leak. - Wait for an ongoing load operation to complete before performing a delete filter operation, so the state stays consistent. - Add `Intent.withSlideInAnimation()` as a simpler and more flexible alternative to `Activity.startActivityWithSlideInAnimation(Intent)`.
This commit is contained in:
parent
0483440381
commit
d200d1e15e
4 changed files with 101 additions and 57 deletions
|
|
@ -0,0 +1,21 @@
|
|||
package com.keylesspalace.tusky.util
|
||||
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.coroutineScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
fun Lifecycle.launchAndRepeatOnLifecycle(
|
||||
state: Lifecycle.State = Lifecycle.State.STARTED,
|
||||
block: suspend CoroutineScope.() -> Unit
|
||||
): Job = coroutineScope.launch {
|
||||
repeatOnLifecycle(state, block)
|
||||
}
|
||||
|
||||
fun LifecycleOwner.launchAndRepeatOnLifecycle(
|
||||
state: Lifecycle.State = Lifecycle.State.STARTED,
|
||||
block: suspend CoroutineScope.() -> Unit
|
||||
): Job = lifecycle.launchAndRepeatOnLifecycle(state, block)
|
||||
Loading…
Add table
Add a link
Reference in a new issue