当前位置: 首页 > news >正文

共享虚拟主机做网站够用么北京城乡建设部网站首页

共享虚拟主机做网站够用么,北京城乡建设部网站首页,怎么做没有后台程序的网站,一站式服务大厅在Android上#xff0c;经常会需要持久化本地数据#xff0c;比如我们需要缓存用户的配置信息、用户的数据、缓存数据、离线缓存数据等等。我们通常使用的工具为SharePreference、MMKV、DataStore、Room、文件等等。通过使用现有的存储框架#xff0c;结合协程#xff0c;我…在Android上经常会需要持久化本地数据比如我们需要缓存用户的配置信息、用户的数据、缓存数据、离线缓存数据等等。我们通常使用的工具为SharePreference、MMKV、DataStore、Room、文件等等。通过使用现有的存储框架结合协程我们可以方便地实现一个轻量级的响应式存储框架。 在使用的场景上我们使用Key-Value的场景很多而且我们往往不仅仅是存储数据、获取数据经常还有需要序列化存储、加密存储、订阅数据的变化的功能。 订阅数据的变化常见的就是使用发布/订阅模式来实现。 但是使用类如EventBus和RxBus并不是一个好的实践EventBus没有做适当的封装被滥用的话会导致逻辑混乱难以跟踪并且调试起来也相当困难。 谷歌的DataStore就是一个很好的实现。除了DataStore我们其实也可以使用基于现有的SharePreference、MMKV通过协程等来实现我们的响应式存储框架。 下面我们就来设计这个存储框架。 首先我们基于我们的功能来定义我们的接口 我们的功能如下 1.支持存储和读取2.支持加密和解密3.支持序列化和反序列化4.支持多“仓库 由此我们定义了3组接口 1.Storage 存储器2.Serializer 序列化器3.CryptoHandler 加密和解密处理器 在清洁架构的分层中存储Storage是属于一种接口适配器因为它为应用的内部业务逻辑即领域层提供了与外部世界即数据库、网络、文件系统等的接口。一般在Respository中和这些接口适配器进行通讯来获取和存储数据所以在设计Storage的时候我们应该遵循下面的概念。 Storage接口定义了一个抽象的存储协议不关注具体的实现方式例如使用SharedPreferencesMMKV或者DataStore这正是适配器层的职责。通过适配器层我们可以使得业务逻辑从具体的技术细节中解耦使其更关注于应用的业务规则而不是底层的存储细节。 同时我们的设计要允许我们根据需要灵活地更换或者修改存储的具体实现而无需改动业务逻辑或者其他部分的代码。 而这正是清洁架构的一个重要原则独立性和隔离变化即依赖抽象而不是具体实现。 基于此设计如下的存储器接口 interface Storage {fun put( key:String, obj:Any?)operator fun T get( key: String, classOfT:ClassT):T?operator fun T get( key: String, typeOfT: Type):T?fun contain( key: String):Booleanfun onKeyChanged( key:String): FlowStringfun remove( key: String)fun removeAllPrefix( prefixKey:String )fun removeExcludePrefix( vararg prefixKey: String )fun clear() } inline operator fun reified T Storage.get(key: String): T? {return get(key, T::class.java) } Storage接口设计将基本的存储操作抽象化并通过onKeyChanged提供了数据变化的通知这是一个非常有用的功能使得可以对存储数据的改变进行反应。 此外removeAllPrefix和removeExcludePrefix方法也为更精细的数据控制提供了可能性这在处理具有特定前缀键值对的场景中非常有用。 Storage接口设计的目的是为了隐藏实现细节和提高代码的可读性、可维护性和可扩展性。 下面我们基于此继续扩展我们的Storage功能 首先我们的数据我们希望是序列化存储的并且可以支持加密。 因此我们继续定义接口 interface Serializer {fun serialize(obj: Any): Stringfun T deserialize(obj: String, classOfT: ClassT): Tfun T deserialize(obj: String, typeOfT: Type): T } inline fun reified T Serializer.deserialize(obj: String): T deserialize(obj, T::class.java) 然后是加密和解密接口 interface CryptoHandler {fun encrypt(obj: String): Stringfun decrypt(obj: String): String }接下来我们就可以使用这两个接口来执行序列化、反序列化加密和解密的操作。 首先MMKV是支持加密的但是MMKV使用的是AES CFB-128加密算法来做的。但是它并不是那么足够安全它没有提供硬件级别的安全加密方法。所以可以考虑自己使用Android KeyStore 来实现硬件级别的加密。 使用Android Keystore来实现一般大致思路就是拿使用Android的keystore 创建一组加密对密钥然后使用AES算法来加密和解密。 序列化我们可以使用ProtoBuf或者是json来实现 下面简单使用gson来实现我们的序列化存储如下 Singleton open class JsonSerializer(private val gson: Gson) : Serializer {override fun serialize(obj: Any): String {return gson.toJson(obj)}override fun T deserialize(obj: String, classOfT: ClassT): T {return gson.fromJson(obj, classOfT)}override fun T deserialize(obj: String, typeOfT: Type): T {return gson.fromJson(obj, typeOfT)} } 定义好了接口实现起来就很简单了只需要在修改key-value的时候发送一个key被修改的消息到一个flow对flow的订阅者就可以订阅数据的改变了。 接下来我们基于MMKV和SharePreference来实现这个存储接口 首先我们来使用SharePreference和MMKV来实现这个存储功能   class SharePreferenceStorage (private val context: Context,private val storageType: StorageType,private val serializer: Serializer,private val eventLogger: StorageLogger?,private val cryptoHandler: CryptoHandler?):Storage{private val sharedPreferences: SharedPreferences context.getSharedPreferences(storageType.alias, Context.MODE_PRIVATE)private val keyChangedFlow MutableSharedFlowString(replay 100)override fun put(key: String, obj: Any?) {obj?.let {data-sharedPreferences.edit().let {editor-editor.putString( key , serializer.serialize( data ).let {cryptoHandler?.encrypt( it )?:it} )editor.apply()keyChangedFlow.tryEmit( key )eventLogger?.trackEvent(StorageSaveEvent( getStorageName(),key, cryptoHandler ! null))}}?: run {remove(key)}}override fun T get(key: String, classOfT: ClassT): T? {sharedPreferences.getString( key ,null )?.let {cryptoHandler?.decrypt( it )?:it}?.let {eventLogger?.trackEvent(StorageLoadEvent( getStorageName(),key, true))serializer.deserialize( it ,classOfT)}?.let {return it}?:run{return null}}override fun T get(key: String, typeOfT: Type): T? {val serializeString sharedPreferences.getString( key ,null )?.let {cryptoHandler?.decrypt( it )?:it}return serializeString?.let {serializer.deserialize( it ,typeOfT)}}override fun onKeyChanged(key: String): FlowString {return keyChangedFlow.asSharedFlow()}override fun contains(key: String): Boolean {return sharedPreferences.contains( key )}override fun remove(key: String) {if( contains( key ) ){sharedPreferences.edit().let {editor-editor.remove( key )editor.apply()keyChangedFlow.tryEmit( key )eventLogger?.trackEvent(StorageRemoveEvent( getStorageName(),key))}}}override fun removeAllPrefix(prefixKey: String) {sharedPreferences.all?.let {allData-allData.keys.filter { it.startsWith( prefixKey ) }.forEach {remove( it )}}}override fun removeExcludePrefix(vararg prefixKey: String) {sharedPreferences.all?.let {allData-val prefixSet prefixKey.toSet()val allKeys allData.keysallKeys.forEach { key -if (prefixSet.none { key.startsWith(it) }) {remove(key)}}}}override fun clear() {sharedPreferences.edit().let {editor-sharedPreferences.all.keys.forEach {remove( it )}keyChangedFlow.tryEmit( CLEAR_CACHE )eventLogger?.trackEvent(StorageClearEvent( getStorageName()))}}private fun getStorageName():String{return SharePreference-${storageType.alias}}} 下面是基于MMKV的实现 class MMKVStorage constructor(private val storageType: StorageType,private val serializer: Serializer,private val eventLogger: StorageLogger?,private val cryptoHandler: CryptoHandler?): Storage {private val mmkv: MMKV MMKV.mmkvWithID( storageType.alias, MMKV.MULTI_PROCESS_MODE)private val keyChangedFlow MutableSharedFlowString(replay 100)private val subscribeKeyList:MutableListString mutableListOf()override fun put(key: String, obj: Any?) {obj?.let {val serializerObj serializer.serialize( obj ).let {cryptoHandler?.encrypt( it )?:it}mmkv.encode( key,serializerObj)keyChangedFlow.tryEmit(key)eventLogger?.trackEvent(StorageSaveEvent( getStorageName(),key, cryptoHandler ! null))} ?: run{remove(key)}}override fun T get(key: String, classOfT: ClassT): T? {return mmkv.decodeString( key )?.let{ jsonString-eventLogger?.trackEvent(StorageLoadEvent( getStorageName(),key, true))serializer.deserialize(jsonString.let {cryptoHandler?.decrypt(it)?:it},classOfT)}}override fun T get(key: String, typeOfT: Type): T? {return mmkv.decodeString( key)?.let { jsonString-eventLogger?.trackEvent(StorageLoadEvent( getStorageName(),key, true))serializer.deserialize( jsonString.let {cryptoHandler?.decrypt(it)?:it}, typeOfT)}}override fun onKeyChanged(key: String): FlowString {subscribeKeyList.add(key)return keyChangedFlow.asSharedFlow().filter { it key }}override fun contains(key: String): Boolean {return mmkv.containsKey( key )}override fun remove(key: String) {mmkv.remove(key).apply()eventLogger?.trackEvent(StorageRemoveEvent( getStorageName(),key))keyChangedFlow.tryEmit( key )}override fun removeAllPrefix( prefixKey:String ){val allKeys mmkv.allKeys()?.clone()?: emptyArray()allKeys.forEach { if( it.contains(prefixKey)) remove(it) }}override fun removeExcludePrefix(vararg prefixKey: String) {val allKeys mmkv.allKeys()?.clone() ?: emptyArray()val prefixSet prefixKey.toSet()allKeys.forEach { key -if (prefixSet.none { key.startsWith(it) }) {remove(key)}}}override fun clear() {mmkv.allKeys()?.forEach {remove(it)}keyChangedFlow.tryEmit( Storage.CLEAR_CACHE )mmkv.clearAll()eventLogger?.trackEvent(StorageClearEvent( getStorageName()))}private fun getStorageName():String {return mmkv-${storageType.alias}}} 通过上面的代码我们就可以实现订阅数据的改变。
http://www.hkea.cn/news/14579086/

相关文章:

  • 注册公司的网站做游戏评论注册国外网站
  • 深圳深网站建设服务软件开发步骤流程
  • 广州 天河网站设计佛山禅城网站建设
  • 做电影网站投资多少苏州建网站需要什么
  • 做数码相的网站邢台企业做网站推广
  • 网站建设情况汇报百度排名
  • 国外网站建设 网站wordpress 弹窗登陆
  • 青岛市工程建设信息网站湖北建设招标网 官方网站
  • 网页浏览器怎么设置苏州网页关键词优化
  • 免费申请空间网站手机网站建设免费
  • 做教程网站犯法吗企业网站的网址通常包含
  • 温州网站设计服务天津建设网证件查询
  • 做美食的视频网站怎么用div做网站
  • 中英文企业网站系统深圳网站建设公司麦
  • 门户网站的营销特点少儿编程10大品牌
  • 公司网站开发建设费用vs2015做网站如何添加控件
  • 广州公司网站设计制作wap 网站的盗链问题
  • 那个网站可以免费做风面广州网站建设乛新科送推广
  • 网站建设亿玛酷知名网站地图有哪些网址
  • 长沙市建设发展集团有限公司网站桂林两江四湖景区导游词
  • 网站手机版建设吴江区桃源镇做网站
  • 管理系统是网站吗网站建设台州
  • 贵州省住房和建设厅网网站首页wordpress个人网站备案管理
  • wordpress 改系统北京优化网站方法
  • 做mp3链接的网站中英文微信网站开发
  • 专门做搞笑游戏视频网站wordpress手机验证码登录界面
  • 网站开头flash怎么做房地产政策
  • 章丘网站建设哪家好做网站的设计软件
  • 泰安网站开发宁国做网站的公司
  • 邯郸网站建设有哪些视频直播平台开发