电子书阅读器上的浏览器 [Day17] 利用 Room 强化书签功能

书签功能在电脑浏览器是个很重要的功能,因为操作方便,所以通常会记录一大堆连结,并且分门别类放在不同的目录中。但是手机上的浏览器,情况略有不同。大部分人比较常用的功能,应该都已经下载对应的 APP 了;剩下一些不常用的服务,才会开启网页偶尔使用;或是需要搜寻网页内容时,会开启浏览器;再来是很大一部分是从其他 APP 中转导到浏览器的。这些应用场景,都不见得需要像电脑上一样,建立书签、管理书签。

但是目前开发中的 browser 的性质又跟一般手机上的浏览器不大一样,因为它是设计给电子纸设备使用的。在电子纸设备上,大部分的 APP 使用体验并不好,所以我预期(至少我自己)使用者在使用电子书阅读器时,除了看电子书外,很多事情是在 browser 上完成的。也因此,有足够强大的书签功能才能符合(我的)需求。

书签目录

原本的书签功能还算堪用,能新增/删除,或是长按书签做修改或其他小功能(加到桌面、存为首页、前景/背景开启新分页)。这次花了点时间,帮它加上了新增目录的功能。

一般电子书阅读器的尺寸至少6寸起跳,所以一个画面可以显示十几二十个书签;但是如果在电子纸手机上的话(像是海信 A5),15 个以上就要开始滑动画面以看到更多的书签。如果能把相同性质的书签放在同个目录,那多按个两下就可以开启网页,会比一直滑动画面来得有效率。

画面1 画面2
https://ithelp.ithome.com.tw/upload/images/20210917/20140260UmcaZvSpgp.png https://ithelp.ithome.com.tw/upload/images/20210917/20140260h6S2Aq5Tu7.png

既然有了书签目录,自然要有方式来把书签放到想要的地方去。所以,在编辑书签的画面多了一个目录选项。Top 表示第一层,其他的选项,就是使用者已经建立的目录名称。建立目录可以在书签页开启後,点三个点按钮,选择新增书签目录 。虽然这方式不是很直觉,而且要一个一个书签去调整,不过,至少是个在有限时间内可以开发出来的功能。

以後有时间的话,再考虑做成可以直接在书签列表用拖拉的方式来调整。

画面3 画面4
https://ithelp.ithome.com.tw/upload/images/20210917/20140260YS29ZJmCNU.png https://ithelp.ithome.com.tw/upload/images/20210917/20140260eyxVq1sFl9.png

技术细节

旧版的书签实作,是直接操作 SQLiteOpenHelper,写了一堆 CRUD 的 SQL 语法,并且要自行处理 cursor 的开开关关。如果我要在这基础上加上目录的功能,感觉会很麻烦,而且很原始。所以我决定把它打掉重练。毕竟,Room 都出来那麽久了,没道理不用比较新的,单纯的作法。

引入 Room 後,先是替书签 data model 加入是否为目录的判断,并为每个书签加上 parent 的概念。

https://ithelp.ithome.com.tw/upload/images/20210917/20140260chx7LijNrQ.png

接下来是建立 Dao interface 来存取资料库。从下面可以看到,这些函式都宣告成 suspend function。这样子之後在使用时,就可以用 coroutine 轻松确保这些操作都不会跑在 main thread 中。

https://ithelp.ithome.com.tw/upload/images/20210917/20140260Jw0w0BReci.png

最後,写个 Manager 把建立资料库实体的实作包装起来:

https://ithelp.ithome.com.tw/upload/images/20210917/20140260HswksKqAzR.png
上面 47 行有个函式叫 migrateOldData(),这是用来将使用者旧版的书签资料搬到新的资料库;也是这次的实作中,唯一接触到 cursor 的部分。搬运完成後,顺手写到 preference 中,以後开启 App 时就不用再搬一次啦。

https://ithelp.ithome.com.tw/upload/images/20210917/201402603emH9e3teH.png

这些都完成後,在 Activity 中需要显示书签时,呼叫上面的 Manager,拿到资料,再喂进 Adapter 就行了。这边针对目录和书签有不同的处理方式,分别在 1212 行和 1214 行:前者是点击後要把画面的书签列表更新为目录中的项目;後者是把画面的网页载入书签连结。

https://ithelp.ithome.com.tw/upload/images/20210917/201402606BY5kzHd2C.png

这样就大致完成啦!

备分/还原书签

这功能主要是因为我有太多台电子书阅读器,平常常用的只有一两台,偶尔要换到别台使用时,苦於上头的 EinkBro 没有完整的书签列表,都得再透过搜寻的方式找到网页。

通常要同步资料的话, App 起手式作法是,跟云端结合,把资料都往云端送。但是我完全不想要让 browser 有把任何资料送到哪个云端去的功能,所以,做个可以把资料备份出来,传送到别台机器上,再用汇入的方式,是目前比较可行的作法。虽然步骤了点,但可以让 browser 不会因为扯上云端而增加复杂度。那类功能就留给 Firefox, Chrome 就好了。

目前的作法很简单,把上面透过 Room 建立好的书签资料库全读出来,转成 json 格式,再写到档案系统中。预设的档名是 bookmarks.json。拿到这档案後,传到另一台设备上,再汇入 json 档就可以了。
这功能是做在设定 → 备份画面中。

https://ithelp.ithome.com.tw/upload/images/20210917/20140260Y1wTVdp7vJ.png

因为不想再引用其他的 json 函式库,所以很简单地包了 JSONObject 的实作:

https://ithelp.ithome.com.tw/upload/images/20210917/20140260SxvWJXFM2p.png

这一篇长了点,稍微复习了一下 Room 的使用方式。下一篇会来谈谈怎麽让目前的 browser 支援夜间模式。


<<:  【Day 17】jQuery事件中的Mouse Events 鼠标事件

>>:  Day 2: 人工智慧在音乐领域的应用 (各层面的应用一)

[Day25] React - 建立React元素

建立元素 我们可以透过以下函式来建立一个React元素: React.cloneElement(el...

Day 2 测试的不同种类

该文章同步发布於:我的部落格 测试的种类 既然要介绍 RSpec,就不得不提到测试的种类,根据下图...

【Day23】导航元件 - Pagination

元件介绍 Pagination 是一个分页元件,当页面中一次要载入过多的资料时,载入及渲染将会花费更...

Day06 捷径的工具箱-App

Hello 大家, 不知不觉来到连假的最後一天了, 要开始收心罗~ 是不是有一些朋友又请了三天特休来...

HERE mSDK - Map Rendering

作为一个地图SDK,最基础最重要的功能首先是地图呈现, 那麽今天我们仍然以 HERE mSDK (P...