diff --git a/LibKeyValue/build.gradle b/LibKeyValue/build.gradle index 0247a4fb7aaeef4747083aa927cf4d5d2c4bc108..1f6fc7bd82abf7f204b8a96c96874cce62027d24 100644 --- a/LibKeyValue/build.gradle +++ b/LibKeyValue/build.gradle @@ -34,12 +34,12 @@ afterEvaluate { groupId = 'com.mx.keyvalue' artifactId = 'MXKeyValue' - version = '1.1.2' + version = rootProject.ext.versionName } } } } dependencies { - + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1' } \ No newline at end of file diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt index 64bd5432f525a227a4c00a1e2bd6b91cfa425889..77272aa9f9515c394f77c8313c142dcbde2dcfa2 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/MXKeyValue.kt @@ -5,9 +5,10 @@ import com.mx.keyvalue.crypt.IKVCrypt import com.mx.keyvalue.crypt.KVNoCrypt import com.mx.keyvalue.store.IKVStore import com.mx.keyvalue.store.sqlite.KVSqliteStore -import com.mx.keyvalue.utils.KVObservable -import com.mx.keyvalue.utils.KVObserver import com.mx.keyvalue.utils.KVUtils +import com.mx.keyvalue.utils.KeyFilter +import com.mx.keyvalue.utils.MXPosition +import kotlin.concurrent.thread class MXKeyValue private constructor(private val context: Context, private val store: IKVStore) { companion object { @@ -50,7 +51,9 @@ class MXKeyValue private constructor(private val context: Context, private val s } } - private val observerSet = HashMap() + init { + thread { store.cleanExpire() } + } /** * 从SharedPreferences拷贝数据 @@ -76,7 +79,6 @@ class MXKeyValue private constructor(private val context: Context, private val s } else { store.delete(key_trim) } - observerSet[key]?.set(value) return result } @@ -96,7 +98,13 @@ class MXKeyValue private constructor(private val context: Context, private val s val key_trim = key.trim() if (key_trim.isBlank()) return false val result = store.delete(key_trim) - observerSet[key]?.set(null) + return result + } + + fun deleteFilter(key: String, position: MXPosition): Boolean { + val key_trim = key.trim() + if (key_trim.isBlank()) return false + val result = store.deleteFilter(KeyFilter(key, position)) return result } @@ -118,22 +126,7 @@ class MXKeyValue private constructor(private val context: Context, private val s return store.cleanAll() } - fun addKeyObserver(key: String, observer: KVObserver) { - var observable = observerSet[key] - if (observable == null) { - observable = KVObservable(key, get(key)) - observerSet[key] = observable - } - observable.addObserver(observer) - } - - fun removeKeyObserver(key: String, observer: KVObserver) { - val observable = observerSet[key] ?: return - observable.deleteObserver(observer) - } - fun release() { - observerSet.clear() store.release() } } \ No newline at end of file diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/store/IKVStore.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/store/IKVStore.kt index 35d4289ff36271c77baed1676393d64f930af38b..f8e1e6e2a598f59d8b3dc0ab7e56ceb14aabdeeb 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/store/IKVStore.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/store/IKVStore.kt @@ -2,6 +2,7 @@ package com.mx.keyvalue.store import android.content.Context import com.mx.keyvalue.crypt.IKVCrypt +import com.mx.keyvalue.utils.KeyFilter interface IKVStore { /** @@ -31,6 +32,12 @@ interface IKVStore { */ fun delete(key: String): Boolean + /** + * 删除所有匹配的键值对 + * @param key 键 + */ + fun deleteFilter(key: KeyFilter): Boolean + /** * 获取所有键值对 */ diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/store/sqlite/KVSqliteStore.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/store/sqlite/KVSqliteStore.kt index 4cfcd7eccba2289b425f0de0e7572880b37dde54..ccad14d84b03d07608f3fcea9f3604bca269e95f 100644 --- a/LibKeyValue/src/main/java/com/mx/keyvalue/store/sqlite/KVSqliteStore.kt +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/store/sqlite/KVSqliteStore.kt @@ -9,6 +9,8 @@ import com.mx.keyvalue.crypt.IKVCrypt import com.mx.keyvalue.crypt.KVNoCrypt import com.mx.keyvalue.store.IKVStore import com.mx.keyvalue.utils.KVUtils +import com.mx.keyvalue.utils.KeyFilter +import com.mx.keyvalue.utils.MXPosition import java.util.concurrent.locks.ReentrantReadWriteLock import kotlin.concurrent.read import kotlin.concurrent.write @@ -129,6 +131,34 @@ class KVSqliteStore : IKVStore { return false } + override fun deleteFilter(key: KeyFilter): Boolean { + lock.write { + val key_filter = when (key.position) { + MXPosition.START -> "${key.filter}%" + MXPosition.END -> "%${key.filter}" + MXPosition.ANY -> "%${key.filter}%" + } + + val database = getDatabase() + try { + database.beginTransaction() + val result = database.delete( + name, + "${KVSQLiteHelper.DB_KEY_NAME} like ?", + arrayOf(key_filter) + ) > 0 + database.setTransactionSuccessful() + return result + } catch (e: Exception) { + e.printStackTrace() + KVUtils.log("delete错误 -> $key -- ${e.message}") + } finally { + database.endTransaction() + } + } + return false + } + override fun getAll(): Map { lock.read { val database = getDatabase() diff --git a/LibKeyValue/src/main/java/com/mx/keyvalue/utils/datas.kt b/LibKeyValue/src/main/java/com/mx/keyvalue/utils/datas.kt new file mode 100644 index 0000000000000000000000000000000000000000..9d360cfbfbf145501f7f9d5bed8b04f7c4fa4c48 --- /dev/null +++ b/LibKeyValue/src/main/java/com/mx/keyvalue/utils/datas.kt @@ -0,0 +1,22 @@ +package com.mx.keyvalue.utils + +enum class MXPosition { + /** + * 模糊匹配 以Key开始 + */ + START, + + /** + * 模糊匹配 以Key结束 + */ + END, + + /** + * 模糊匹配 Key在字段中的任意位置 + */ + ANY +} + +data class KeyFilter( + val filter: String, val position: MXPosition = MXPosition.ANY +) \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3fdb13469b6489b07192ee28db324ce45398770a..9ca7c61071b2bb4b2eb48aa6a68bbcd29f84ed18 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -22,6 +22,7 @@ + \ No newline at end of file diff --git a/app/src/main/java/com/mx/example/app/KeyFilterTestActivity.kt b/app/src/main/java/com/mx/example/app/KeyFilterTestActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..10db04be23151fc597a55d9704af33202cc3be6a --- /dev/null +++ b/app/src/main/java/com/mx/example/app/KeyFilterTestActivity.kt @@ -0,0 +1,36 @@ +package com.mx.example.app + +import android.os.Bundle +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.mx.example.databinding.ActivityKeyFilterTestBinding +import com.mx.example.utils.SPUtils +import com.mx.keyvalue.utils.MXPosition + +class KeyFilterTestActivity : AppCompatActivity() { + private val binding by lazy { ActivityKeyFilterTestBinding.inflate(layoutInflater) } + private val key_pre = "KEY_PRE_TEST" + private val key_position = MXPosition.ANY + private val key_name = when (key_position) { + MXPosition.START -> "${key_pre}_aaa" + MXPosition.END -> "aaa_${key_pre}" + MXPosition.ANY -> "bbb_${key_pre}_aaa" + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + + binding.setExpireTxv.setOnClickListener { + SPUtils.set(key_name, "1分钟失效:" + System.currentTimeMillis()) + Toast.makeText(this, "已设置$key_name", Toast.LENGTH_SHORT).show() + } + binding.deleteTxv.setOnClickListener { + SPUtils.deleteFilter(key_pre, key_position) + Toast.makeText(this, SPUtils.get(key_name, "失效"), Toast.LENGTH_SHORT).show() + } + binding.readExpireTxv.setOnClickListener { + Toast.makeText(this, SPUtils.get(key_name, "失效"), Toast.LENGTH_SHORT).show() + } + } +} diff --git a/app/src/main/java/com/mx/example/app/MainActivity.kt b/app/src/main/java/com/mx/example/app/MainActivity.kt index a5d87115a7e524c963055c5747dd1ff6f2bc6b1c..8217f6167e0a41ff49dc334e707b418ea4c6ef0b 100644 --- a/app/src/main/java/com/mx/example/app/MainActivity.kt +++ b/app/src/main/java/com/mx/example/app/MainActivity.kt @@ -20,5 +20,8 @@ class MainActivity : AppCompatActivity() { binding.delegateTestTxv.setOnClickListener { startActivity(Intent(this, DelegateTestActivity::class.java)) } + binding.keyFilterTestTxv.setOnClickListener { + startActivity(Intent(this, KeyFilterTestActivity::class.java)) + } } } diff --git a/app/src/main/java/com/mx/example/utils/SPUtils.kt b/app/src/main/java/com/mx/example/utils/SPUtils.kt index be126225212a1fb493e0e07bd8b4f210bc992c31..32330343e533db2ac23ee311b311ceff2617f4bd 100644 --- a/app/src/main/java/com/mx/example/utils/SPUtils.kt +++ b/app/src/main/java/com/mx/example/utils/SPUtils.kt @@ -7,6 +7,7 @@ import com.mx.keyvalue.MXKeyValue import com.mx.keyvalue.crypt.KVAESCrypt import com.mx.keyvalue.delegate.KVBaseDelegate import com.mx.keyvalue.store.sqlite.KVSqliteStore +import com.mx.keyvalue.utils.MXPosition // 缓存类 object SPUtils { @@ -33,6 +34,10 @@ object SPUtils { return KV.delete(key) } + fun deleteFilter(key: String, position: MXPosition): Boolean { + return KV.deleteFilter(key, position) + } + class KVBeanDelegate( kv: MXKeyValue, private val clazz: Class, diff --git a/app/src/main/res/layout/activity_key_filter_test.xml b/app/src/main/res/layout/activity_key_filter_test.xml new file mode 100644 index 0000000000000000000000000000000000000000..33395e46292b7fe9b0df99aff20ea103e703decb --- /dev/null +++ b/app/src/main/res/layout/activity_key_filter_test.xml @@ -0,0 +1,30 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index bcaad9167e2aab44a74c9d275090ddd599774a89..831548f14460b00b0de5fb62ae87211b45756eba 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -27,4 +27,11 @@ android:layout_height="wrap_content" android:padding="10dp" android:text="对象代理测试" /> + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ebf1ed6f12447b410f10d376839c8ca731f7d850..1ac13c8171e865aeab034263a4632a6aa287e7d6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,3 @@ - MXDialog + MXKeyValue \ No newline at end of file diff --git a/build.gradle b/build.gradle index 82861ce9cb8895329e40c0e64f8aa672155b0fcc..6df93f5a1f4229d0892b0fccbf8ded23e9aef53b 100644 --- a/build.gradle +++ b/build.gradle @@ -16,5 +16,5 @@ ext { minSdkVersion = 21 versionCode = 1 - versionName = "1.2.2" + versionName = "1.3.0" } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 6255acdadadcf38d95dbf9d6b5115cb92b94bddf..b2c4871f51cd480095015d5e7c6ecdc8064e201d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,7 +3,6 @@ pluginManagement { maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/public' } maven { url 'https://jitpack.io' } - maven { url "https://mvn.mob.com/android" } gradlePluginPortal() google() mavenCentral() @@ -15,7 +14,6 @@ dependencyResolutionManagement { maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/public' } maven { url 'https://jitpack.io' } - maven { url "https://mvn.mob.com/android" } google() mavenCentral() }