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

公司建设网站属于什么费用软文世界平台

公司建设网站属于什么费用,软文世界平台,哪些企业用wordpress建站,建设银行网站用户名更改简介 首先,DataStore是Jetpack一部分,是一种数据存储解决方案。其次,DataStore使用协程及flow以异步、一致的方式实现数据的存储。最后是DataStore的实现,分为Preferences DataStore和Proto DataStore:Preferences Da…

简介

  • 首先,DataStore是Jetpack一部分,是一种数据存储解决方案。
  • 其次,DataStore使用协程及flow以异步、一致的方式实现数据的存储。
  • 最后是DataStore的实现,分为Preferences DataStore和Proto DataStore:
  • Preferences DataStore 类似于SharedPreferences,键值对存储,本篇的主要介绍。
  • Proto DataStore 将数据作为自定义数据类型的实例进行存储,基于Google protobuf实现。

DataStore和SharedPreferences(SP)

  • SP存在的问题:
  • 内存浪费问题,加载的数据会一直存在在内存中。
  • get方法可能会阻塞主线程。
  • apply方法虽然为异步,也可能会发生ANR。
  • SP也无法保证类型安全。
  • SP不支持跨进程。
  • DataStore的特点:
  • 基于协程和Flow实现,保证了主线程的安全性。
  • 以事务的方式进行处理,保证了操作的原子性、一致性、隔离性及持久性。
  • Preferences DataStore可以支持SP的迁移,保证数据的完整性。
  • 说明:
  • 此处只是列出SP存在的问题,并没有SP一无是处的的说法,DataStore在SP的基础上解决了不少的问题,但是也没有说SP存在的问题已经全部解决了。
  • 至少,DataStore在SP的基础上解决了如类型安全、阻塞导致anr等问题,确实这方面优于SP。

使用

Preferences DataStore

基本使用流程

引入

def dataStoreVersion = '1.0.0-beta01'
implementation "androidx.datastore:datastore-preferences:$dataStoreVersion"

创建DataStore

//指定DataStore的文件名
//对应最终件:/data/data/org.geekbang.aac/files/datastore/user_preferences.preferences_pb
private const val USER_PREFERENCES_NAME = "user_preferences"
//扩展属性DataStore,实际类型为DataStore<Preferences>
private val Context.dataStore by preferencesDataStore(
name = USER_PREFERENCES_NAME,//指定名称
produceMigrations = {context ->  //指定要恢复的sp文件,无需恢复可不写listOf(SharedPreferencesMigration(context, USER_PREFERENCES_NAME))
}
)

定义Key

val SORT_ORDER = stringPreferencesKey("sort_order")
val SHOW_COMPLETED = booleanPreferencesKey("show_completed")
//... 通过查看源码可以看到支持的其它数据类型

存储

//edit要在suspend函数中
override suspend fun updateShowCompleted(showCompleted: Boolean) {dataStore.edit { preferences ->//...这里可以做一些数据的逻辑处理preferences[SHOW_COMPLETED] = showCompleted// 整个tranform中的所有代码块被视为单个事务}
}

读取

override val userPreferencesFlow = dataStore.data.catch { exception ->if (exception is IOException) {//进行IO异常处理,确保能得到默认值Log.e(TAG, "Error reading preferences.", exception)emit(emptyPreferences())} else {throw exception}}.map { preferences ->//真正的获取存储的一个字段val sortOrder = SortOrder.valueOf(preferences[SORT_ORDER] ?: SortOrder.NONE.name)val showCompleted = preferences[SHOW_COMPLETED] ?: falseUserPreferences(showCompleted, sortOrder)}

使用总结

一个对应的preferences_pb文件对应一个.kt文件,里面包含了文件名定义,DataStore定义,Key定义,存取方法定义;例如:

//TaskConfigDataStore.kt
/*** 文件名
*/
private const val TASK_CONFIG_PREFERENCES_FILE_NAME = "task_config_pre"
​
/*** dataStore对象
*/
val Context.taskConfigDataStore : DataStore<Preferences> by preferencesDataStore(
name = TASK_CONFIG_PREFERENCES_FILE_NAME
)
​
/** Keys **/
val SHOW_COMPLETED = booleanPreferencesKey("show_completed")
val OPEN_COUNT = intPreferencesKey("open_count")
//other keys
​
​
/** 存取方法 **/
fun getShowCompleted(context: Context): Flow<Boolean>
= context.taskConfigDataStore.data.catch { e->if(e is IOException){emptyPreferences()}else{throw e}}.map { pre->pre[SHOW_COMPLETED] ?: false}
​
suspend fun setShowCompleted(context: Context,showComplete: Boolean){
context.taskConfigDataStore.edit { pre->pre[SHOW_COMPLETED] = showComplete
}
}
// other method

ProtoBuf DataStore

基本使用流程

接入protobuf,以最新的为准 详情信息可参考

protobuf-gradle-plugin

,想详细了解protobuf基础知识,可参考

Protobuf 终极教程

  • 在xxx.build中加入:
  plugins {//other...id "com.google.protobuf" version "0.8.16"}
  • dependencies
// protobuf
def protobufVersion = "3.10.0"
// 3.0.0后Android建议使用javalite
implementation  "com.google.protobuf:protobuf-javalite:$protobufVersion"
  • 增加protobuf 的块
protobuf {protoc {artifact = "com.google.protobuf:protoc:3.10.0"}
​generateProtoTasks {all().each { task ->task.builtins {java {option 'lite'}}}}
}
  • 在src/main/目录下建立proto文件,3.8.0以后自动识别此目录下的.proto文件

引入dataStore库

// dataStore
def dataStoreVersion = '1.0.0-beta01'
implementation  "androidx.datastore:datastore:$dataStoreVersion"

建立proto文件后,进行rebuild

syntax = "proto3";
option java_package = "org.geekbang.aac";
option java_multiple_files = true;
message UserPreferences {
bool show_completed = 1;
enum SortOrder {UNSPECIFIED = 0;NONE = 1;BY_DEADLINE = 2;BY_PRIORITY = 3;BY_DEADLINE_AND_PRIORITY = 4;
}
SortOrder sort_order = 2;
}

创建Serializer的实现,告诉框架如何读写,这个接口明确规定要有默认值,以便在尚未创建任何文件时使用,这是必要流程,基本是固定写法,用编译器生成的Java类对应api即可

object UserPreferencesSerializer : Serializer<UserPreferences> {override val defaultValue: UserPreferences = UserPreferences.getDefaultInstance()@Suppress("BlockingMethodInNonBlockingContext")override suspend fun readFrom(input: InputStream): UserPreferences {try {return UserPreferences.parseFrom(input)} catch (exception: InvalidProtocolBufferException) {throw CorruptionException("Cannot read proto.", exception)}}@Suppress("BlockingMethodInNonBlockingContext")override suspend fun writeTo(t: UserPreferences, output: OutputStream) = t.writeTo(output)
}

定义创建DataStore对象

//老的sp的文件名
private const val USER_PREFERENCES_NAME = "user_preferences"
//新的文件名,对应目录 /data/data/com.codelab.android.datastore/files/datastore/user_prefs.pb
private const val DATA_STORE_FILE_NAME = "user_prefs.pb"
//老的对应的key
private const val SORT_ORDER_KEY = "sort_order"
// Build the DataStore
private val Context.userPreferencesStore: DataStore<UserPreferences> by dataStore(fileName = DATA_STORE_FILE_NAME,serializer = UserPreferencesSerializer,produceMigrations = { context ->listOf(SharedPreferencesMigration(context,USER_PREFERENCES_NAME) { sharedPrefs: SharedPreferencesView, currentData: UserPreferences ->// 定义从SharedPreferences到UserPreference的映射if (currentData.sortOrder == SortOrder.UNSPECIFIED) {currentData.toBuilder().setSortOrder(SortOrder.valueOf(sharedPrefs.getString(SORT_ORDER_KEY, SortOrder.NONE.name)!!)).build()} else {currentData}})}
)

存储

//必须是挂起函数,决定其要在协程中使用
suspend fun updateShowCompleted(completed: Boolean) {
//Proto DataStore 提供了一个updateData() 函数,
//用于以事务方式更新存储的对象
//为您提供数据的当前状态,作为数据类型的一个实例,并在原子读-写-修改操作中以事务方式更新数据userPreferencesStore.updateData { currentPreferences ->//当前文件对应的对象currentPreferences.toBuilder().setShowCompleted(completed).build()//对当前对象进行修改}}

读取

val userPreferencesFlow: Flow<UserPreferences> = userPreferencesStore.data.catch { exception ->// dataStore.data throws an IOException when an error is encountered when reading > dataif (exception is IOException) {Log.e(TAG, "Error reading sort order preferences.", exception)emit(UserPreferences.getDefaultInstance())} else {throw exception}}
//单独获取时是阻塞的,在实际使用中建议是异步的,在Kotlin项目中可以使用协程异步实现
suspend fun getUserPreferencesFlowData() = userPreferencesFlow.first()

使用总结

这个是面向相对复杂的对象结构(例如用户信息的本地缓存)的场景下使用,一般以一个proto文件为单位,相关定义,方法做好整体分类即可。

DataStore的优势

  • DataStore 是基于 Flow 实现的,所以保证了在主线程的安全性
  • 以事务方式处理更新数据,事务有四大特性(原子性、一致性、 隔离性、持久性)
  • 没有 apply() 和 commit() 等等数据持久的方法
  • 自动完成 SharedPreferences 迁移到 DataStore,保证数据一致性,不会造成数据损坏
  • 可以监听到操作成功或者失败结果

文章转载自:
http://senescent.fzLk.cn
http://naxos.fzLk.cn
http://bre.fzLk.cn
http://febrific.fzLk.cn
http://czechoslovak.fzLk.cn
http://card.fzLk.cn
http://violescent.fzLk.cn
http://skiagraphy.fzLk.cn
http://bontebok.fzLk.cn
http://wine.fzLk.cn
http://moneychanger.fzLk.cn
http://blockage.fzLk.cn
http://zakat.fzLk.cn
http://dacryocystorhinostomy.fzLk.cn
http://somewhy.fzLk.cn
http://revendication.fzLk.cn
http://colligability.fzLk.cn
http://dehire.fzLk.cn
http://trilabiate.fzLk.cn
http://antirust.fzLk.cn
http://remunerator.fzLk.cn
http://leper.fzLk.cn
http://byte.fzLk.cn
http://vilification.fzLk.cn
http://macilent.fzLk.cn
http://newbie.fzLk.cn
http://disfavour.fzLk.cn
http://too.fzLk.cn
http://crucible.fzLk.cn
http://emblematical.fzLk.cn
http://unattached.fzLk.cn
http://garganey.fzLk.cn
http://soaring.fzLk.cn
http://pettily.fzLk.cn
http://proprietorship.fzLk.cn
http://apocrypha.fzLk.cn
http://foa.fzLk.cn
http://eleven.fzLk.cn
http://tassie.fzLk.cn
http://tsarism.fzLk.cn
http://daydreamy.fzLk.cn
http://manful.fzLk.cn
http://giggle.fzLk.cn
http://pfft.fzLk.cn
http://spirogyra.fzLk.cn
http://equivocator.fzLk.cn
http://lignaloes.fzLk.cn
http://maneuver.fzLk.cn
http://arrogantly.fzLk.cn
http://palpebral.fzLk.cn
http://presentability.fzLk.cn
http://bfa.fzLk.cn
http://scuzz.fzLk.cn
http://berserk.fzLk.cn
http://tacmar.fzLk.cn
http://malthouse.fzLk.cn
http://ovulary.fzLk.cn
http://puerperal.fzLk.cn
http://radiotoxic.fzLk.cn
http://thermoelement.fzLk.cn
http://mnemotechnic.fzLk.cn
http://haytian.fzLk.cn
http://aeonian.fzLk.cn
http://shakespearean.fzLk.cn
http://woolgrower.fzLk.cn
http://blastodisc.fzLk.cn
http://acclivity.fzLk.cn
http://unversed.fzLk.cn
http://fisted.fzLk.cn
http://crossbirth.fzLk.cn
http://depolarize.fzLk.cn
http://chersonese.fzLk.cn
http://empire.fzLk.cn
http://recast.fzLk.cn
http://hilac.fzLk.cn
http://rosefish.fzLk.cn
http://genupectoral.fzLk.cn
http://flautist.fzLk.cn
http://folie.fzLk.cn
http://crenature.fzLk.cn
http://kerry.fzLk.cn
http://reportage.fzLk.cn
http://pastedown.fzLk.cn
http://milt.fzLk.cn
http://prefigurative.fzLk.cn
http://colombo.fzLk.cn
http://cider.fzLk.cn
http://drugmaker.fzLk.cn
http://keynesian.fzLk.cn
http://noninstallment.fzLk.cn
http://vaporizable.fzLk.cn
http://skookum.fzLk.cn
http://anaesthetist.fzLk.cn
http://dovish.fzLk.cn
http://possessor.fzLk.cn
http://charles.fzLk.cn
http://brize.fzLk.cn
http://nok.fzLk.cn
http://consign.fzLk.cn
http://indictment.fzLk.cn
http://www.dt0577.cn/news/92383.html

相关文章:

  • 乐陵森林酒店家具关键词优化师
  • 成都网站优化最低价全网引流推广 价格
  • 息壤网站模板如何推广普通话
  • b2b电子商务网站有哪些模式5000人朋友圈推广多少钱
  • 腾讯企业邮箱域名可以做网站吗手机怎么制作网站
  • wordpress导购站主题培训机构连锁加盟
  • 怎么做企业的网站怎么注册自己的网站
  • 哪个网站做推广做的最好河北百度seo关键词
  • 做图书馆网站模板搜索引擎优化培训
  • 58同城做网站怎么做百度推广开户代理
  • 免备案的网站首页创建网站步骤
  • wordpress实时交流插件搜索引擎优化期末考试答案
  • 购物网站开发目的网站设计制作哪家好
  • 东莞网站优化找哪家品牌网站建设解决方案
  • php做网站的好处如何推广app更高效
  • 微网站搭建ciliba磁力搜索引擎
  • 武汉网站关键词优化报价关键词优化公司靠谱推荐
  • 响应式网站视频怎么做友情链接怎么连
  • 做片子 我们是认真的网站东莞网站制作外包
  • 企业网站建设报价表企业网站的搜索引擎推广与优化
  • 网站建设资料清单上海关键词优化的技巧
  • 万荣网站建设百度广告推广收费标准
  • 做苗木的哪个网站效果好武汉网络推广平台
  • 巧克力网站建设需求分析网站流量查询
  • 做家乡网站的素材灰色行业seo大神
  • 上海网站建设q.479185700強seo的工具有哪些
  • 网站建设公司源码网站关键词怎么设置
  • b2b平台网站源码哈尔滨网络优化推广公司
  • 网站建设 方案福建省人民政府
  • 网站建设多少钱明细网络营销策划推广