ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

B10_文件SharedPreferences与SQLite

B10_文件SharedPreferences与SQLite Android 基础补强 B10文件、SharedPreferences 与 SQLite数据该放在哪里摘要分别保存学习草稿、界面偏好和文章记录比较三种传统持久化方式的数据形态、更新成本及失败处理再连接 DataStore 与 Room。标签Android、SQLite、SharedPreferences、文件存储、第一行代码本文对应《第一行代码》第 3 版第 7 章也为 28 天课程 D12、D13、D15 补充存储基础。选择存储工具之前先问数据如何读取、如何更新、需要什么约束。文中的练习片段未编译运行不修改你的项目数据库真实迁移需要先明确已有 schema 和数据保留要求。1. 三种数据三种访问方式一份学习草稿通常整体读取、整体编辑文件容易表达主题偏好是一小组键值读取时需要默认值收藏文章需要按 ID 去重、按时间排序、按条件查询更适合关系型数据库。把收藏列表转成 JSON 塞进一个偏好键并非绝对做不到但每次修改都要解码、替换和写回整份数据约束也由自己承担。文件格式自由意味着应用负责编码、完整性与版本。键值存储操作简洁但不擅长复杂关联。数据库有 schema、查询和事务学习成本更高却能把某些正确性要求交给结构表达。选择时比较的是实际操作不是给三种工具排一个抽象优劣名次。2. 文件路径、编码和关闭资源应用专属内部存储适合不需要直接共享给其他应用的文件。通过 Context 提供的目录或文件 API 获取路径不硬编码不同设备上的绝对目录也要区分长期文件与可被系统回收的缓存目录。应用专属文件指南下面把草稿写入内部文件放在 Repository 的挂起函数中。ioDispatcher通过构造器注入便于替换测试调度器context使用合适的应用级 Context。代码演示资源关闭和离开主线程不包含备份或原子替换等完整文档编辑能力。suspendfunsaveDraft(text:String)withContext(ioDispatcher){context.openFileOutput(learning_draft.txt,Context.MODE_PRIVATE).bufferedWriter(Charsets.UTF_8).use{writer-writer.write(text)}}suspendfunreadDraft():StringwithContext(ioDispatcher){context.openFileInput(learning_draft.txt).bufferedReader(Charsets.UTF_8).use{reader-reader.readText()}}首次读取文件可能不存在应在调用边界把“没有保存过草稿”与“读取失败”分开处理。文件写入中断也可能留下不完整内容重要草稿可以采用受支持的原子文件机制或临时文件替换策略并验证失败恢复。一个use解决关闭资源不自动保证整份业务数据原子提交。3. SharedPreferences理解旧工程的键值更新传统设置可以通过getSharedPreferences(settings, MODE_PRIVATE)读取使用 Editor 写入。读取时给出的默认值是键不存在时的业务选择不说明磁盘里一定已经保存了这个值。键名及值类型也属于持久格式后续版本不能随意把同一键由字符串改成数字。valprefscontext.getSharedPreferences(settings,Context.MODE_PRIVATE)valshowAuthorprefs.getBoolean(show_author,true)prefs.edit().putBoolean(show_author,false).apply()apply先更新内存并异步写磁盘不返回磁盘写入是否成功commit同步执行并返回结果因此不应在主线程随意进行可能阻塞的写入。也不能由“异步”推断完全没有性能代价。新功能的小型设置应结合 DataStore 指南选择学习 SharedPreferences 主要帮助阅读书本与维护存量实现。SharedPreferences 官方说明如果两个地方分别读取旧值、加一、写回即便单次写入能够提交也不代表整个读改写过程没有竞争。学习存储时要把“单次写入”和“跨多步操作的原子性”分开不能因为 API 简单就忽略并发语义。4. SQLite结构、参数与事务收藏文章需要唯一 ID可以在表结构中定义主键按照时间倒序展示使用带排序的查询按 ID 删除则用参数绑定表达目标。下面是 SQL 练习并非完整 SQLiteOpenHelper问号应由查询 API 的参数传入不与用户输入直接拼接。CREATETABLEbookmark(article_idINTEGERPRIMARYKEY,titleTEXTNOTNULL,created_atINTEGERNOTNULL);SELECTarticle_id,title,created_atFROMbookmarkWHEREcreated_at?ORDERBYcreated_atDESC,article_idDESC;DELETEFROMbookmarkWHEREarticle_id?;使用 Cursor 时需要关闭访问磁盘也不应阻塞主线程。多个写入必须同时成功时使用事务异常时回滚不能只依赖“这几行代码挨着写”。修改表结构还需要迁移方案直接删表重建会丢失用户收藏不是通用升级策略。SQLite 存储指南Room 在这些概念之上提供实体、DAO、查询校验与迁移组织并不取消主键、索引或事务的意义。先读懂一条 SQL再看对应 DAO 注解可以避免把数据库理解成只会调用insert的黑盒。5. 用同一组失败检查存储边界文件实验保存带换行的中文草稿重启后读取预期编码和换行保留再删除测试文件确认首次无文件不会被误报成内容为空且保存成功。偏好实验切换作者显示开关再重启预期恢复选择清除测试键后应回到约定默认值。数据库实验连续插入相同 ID观察所选冲突策略然后按时间查询并核对相同时间的稳定次序。再在包含两个写入的测试事务中制造异常预期两步共同回滚。每次只改一个条件并在专用测试数据上操作避免把真实收藏当作故障样本。这些是操作与预期未代表实际测试通过。完成后记录输入、存储结果和重启行为便能说明三种方式分别保存了什么而不是只展示调用过几个 API。6. 原创面试问答与追问问一为什么不把所有数据都放 SharedPreferences复杂列表查询、唯一约束与关联更新会变成手工维护。追问很小的列表一定不能放吗可以但要承认格式、并发和整份重写的成本。问二apply 返回后就保证磁盘保存成功吗不能这样理解它异步写盘且不返回结果。追问改 commit 就能主线程随便写吗不能同步磁盘操作可能阻塞界面。问三Room 出现后还有必要学 SQLite 吗有DAO 查询仍依赖 SQL 语义。追问最先掌握什么主键、过滤、排序、参数绑定、事务与迁移的数据保留规则。问答为原创补强非面试鸭原题。验收时能为草稿、偏好与收藏各选一种方式并说明理由能解释失败与重启行为再连接 D12 的 Room 和 D15 的 DataStore就完成了第 7 章的基础闭环。
返回列表