perf: 优化数据存储逻辑

This commit is contained in:
lisonge 2023-11-09 16:19:09 +08:00
parent 1c7df7e751
commit df39f35317

View File

@ -1,81 +1,47 @@
package li.songe.gkd.util
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import com.blankj.utilcode.util.LogUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import li.songe.gkd.app
import li.songe.gkd.appScope
import java.util.WeakHashMap
private val onReceives by lazy {
mutableListOf<(
context: Context?,
intent: Intent?,
) -> Unit>()
}
private val receiver by lazy {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
onReceives.forEach { fc -> fc(context, intent) }
}
}.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
app.registerReceiver(this, IntentFilter(app.packageName), Context.RECEIVER_NOT_EXPORTED)
} else {
app.registerReceiver(this, IntentFilter(app.packageName))
}
}
}
val stateFlowToKey by lazy { WeakHashMap<StateFlow<*>, String>() }
private inline fun <reified T> createStorageFlow(
key: String,
crossinline init: () -> T,
): StateFlow<T> {
val stateFlow =
MutableStateFlow(kv.getString(key, null)?.let { Singleton.json.decodeFromString<T>(it) }
?: init())
onReceives.add { _, intent ->
val extras = intent?.extras ?: return@add
val type = extras.getString("type") ?: return@add
val itKey = extras.getString("key") ?: return@add
if (type == "update_storage" && itKey == key) {
stateFlow.value =
kv.getString(key, null)?.let { Singleton.json.decodeFromString<T>(it) } ?: init()
val str = kv.getString(key, null)
val initValue = if (str != null) {
try {
Singleton.json.decodeFromString<T>(str)
} catch (e: Exception) {
e.printStackTrace()
LogUtils.d(e)
null
}
} else {
null
}
val stateFlow = MutableStateFlow(initValue ?: init())
appScope.launch {
stateFlow.drop(1).collect {
withContext(Dispatchers.IO) {
kv.encode(key, Singleton.json.encodeToString(it))
}
}
}
stateFlowToKey[stateFlow] = key
return stateFlow
}
fun sendStorageBroadcast(key: String) {
app.sendBroadcast(Intent(app.packageName).apply {
`package` = app.packageName
putExtra("type", "update_storage")
putExtra("key", key)
})
fun <T> updateStorage(stateFlow: StateFlow<T>, newState: T) {
(stateFlow as MutableStateFlow).value = newState
}
inline fun <reified T> updateStorage(stateFlow: StateFlow<T>, newState: T) {
if (stateFlow.value == newState) return
val key = stateFlowToKey[stateFlow] ?: error("not found stateFlow key")
kv.encode(key, Singleton.json.encodeToString(newState))
sendStorageBroadcast(key)
}
@Serializable
data class Store(
val enableService: Boolean = true,
@ -113,6 +79,8 @@ val clickCountFlow by lazy {
recordStoreFlow.map(appScope) { r -> r.clickCount }
}
private val log2FileSwitchFlow by lazy { storeFlow.map(appScope) { s -> s.log2FileSwitch } }
fun increaseClickCount(n: Int = 1) {
updateStorage(
recordStoreFlow,
@ -121,11 +89,10 @@ fun increaseClickCount(n: Int = 1) {
}
fun initStore() {
receiver
storeFlow.value
recordStoreFlow.value
appScope.launchTry(Dispatchers.IO) {
storeFlow.map(appScope) { s -> s.log2FileSwitch }.collect {
log2FileSwitchFlow.collect {
LogUtils.getConfig().isLog2FileSwitch = it
}
}