Cleanup rememberMemorized

This commit is contained in:
tarsin committed 2023-07-10 19:27:44 +08:00
1 parent 407c55dbdc
commit 3f6abd6380
2 files changed
+16 -43

No files matched your search

@@ -32,8 +32,6 @@ import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.navigation.fragment.findNavController
import androidx.paging.Pager
@@ -70,10 +68,7 @@ import kotlinx.coroutines.launch
import moe.tarsin.coroutines.runSuspendCatching
import my.nanihadesuka.compose.LazyGridScrollbar
class VMStorage1 : ViewModel()
class GalleryPreviewScreen : Fragment() {
private val vm: VMStorage1 by viewModels()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = ComposeView(inflater.context).apply {
setMD3Content {
val galleryDetail = remember { requireArguments().getParcelableCompat<GalleryDetail>(KEY_GALLERY_DETAIL)!! }
@@ -128,7 +123,7 @@ class GalleryPreviewScreen : Fragment() {
}
override val jumpingSupported = true
}
}.flow.cachedIn(vm.viewModelScope)
}.flow.cachedIn(viewModelScope)
}.collectAsLazyPagingItems()
Scaffold(
@@ -2,54 +2,32 @@ package com.hippo.ehviewer.ui.tools
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.currentCompositeKeyHash
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.saveable.LocalSaveableStateRegistry
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
private val remembered = hashMapOf<String, Any>()
class StateMapViewModel : ViewModel() {
val states: MutableMap<Int, ArrayDeque<Any>> = mutableMapOf()
}
// This works mostly like [rememberSaveable], but saves data in global hashmap, to avoid [TransactionTooLargeException]
@Composable
fun <T : Any> rememberMemorized(
vararg inputs: Any?,
key: String? = null,
init: () -> T,
init: ViewModel.() -> T,
): T {
// key is the one provided by the user or the one generated by the compose runtime
val finalKey = if (!key.isNullOrEmpty()) {
key
} else {
// currentCompositeKeyHash is unreliable here
// Is this Composable inlined or its groups elided?
// Or a compose compiler bug?
init.javaClass.toString()
}
val registry = LocalSaveableStateRegistry.current
// value is restored using the registry or created via [init] lambda
val vm: StateMapViewModel = viewModel()
val key = currentCompositeKeyHash
val value = remember(*inputs) {
val states = vm.states[key] ?: ArrayDeque<Any>().also { vm.states[key] = it }
@Suppress("UNCHECKED_CAST")
val restored = registry?.consumeRestored(finalKey)?.let {
remembered.remove(it as String)
} as T?
restored ?: init()
states.removeFirstOrNull() as T? ?: init(vm)
}
// re-register if the registry or key has been changed
if (registry != null) {
// we want to use the latest instances of saver and value in the valueProvider lambda
// without restarting DisposableEffect as it would cause re-registering the provider in
// the different order. so we use rememberUpdatedState.
val valueState = rememberUpdatedState(value)
DisposableEffect(registry, finalKey) {
val valueProvider = {
finalKey.also { remembered[it] = valueState.value }
}
val entry = registry.registerProvider(finalKey, valueProvider)
onDispose {
entry.unregister()
}
val valueState = rememberUpdatedState(value)
DisposableEffect(key) {
onDispose {
vm.states[key]?.addFirst(valueState.value)
}
}
return value