相册备份的核心问题就是将本地相册中的数据同步到 COS 上,需求很清晰,模型似乎也很简单。
[图片上传失败...(image-2c21d2-1607425597634)]
很明显,这里有两个模块,一个是本地相册数据,另一个是备份的 COS 路径(一般包括 region、bucket 和 prefix)。由此我们定义 AlbumDataSource 来表示相册数据,COSBackupEndpoint 表示 COS 备份路径。我们从 AlbumDataSource 中 list 出所有的文件,然后和 BackupEndpoint 一起生成一系列的 BackupTask,并交给 BackupTaskService 执行即可。
然而事情显然没有那么简单,首先因为相册备份很难一次性完成,因此我们还需要保存当前的备份状态,下次备份时能够继续备份,这里我们定义一个 BackupSnapshot 来保存所有备份任务的状态。
这样我们每次开始备份时,总是会
-
通过调用 AlbumDataSource#listAll() 来查询当前相册的所有文件;
-
查询当前 BackupEndpoint 和 BackupSnapshot;
-
通过一个 TaskCreator 生成 Task 列表;
-
通过 Task 列表生成一个 BackupTaskProvider,然后交给 BackupTaskService 去执行备份任务,并刷新备份快照;
目前看起来很美好了,但是产品不会让我们那么开心,给我们增加了几个新的需求:
-
允许设置备份图片还是视频;
-
备份路径是可变的;
-
相册新增文件后,需要实时备份;
我们可以通过修饰器模式增加一个 FilteredAlbumDataSource 来处理备份类型,同时,如果相册文件、备份类型或者备份路径发送了变化,都需要调用 BackupTaskService#getDefault().cancel() 先取消备份,然后调用 TaskCreator 重新生成备份任务进行备份;
过了几天,产品又出幺蛾子了,又提了如下几个需求:
-
要求用户的 BackupEndpoint 可以多端同步,也就是我们需要在 app 启动的时候去拉取云端的设置,当用户修改后,需要将其同步到云端。
-
备份任务允许设置仅在 wifi 状态下备份;
这个两个需求变更还是很好实现的,首先我们只需要抽象出一个 BackupEndpointManager 类,它允许合并本地和网络的 BackupEndpoint 数据,并将新的设置同步到云端。其次,我们给 BackupTaskService 持有一个 NetworkService 来获得当前网络状态的回调,并处理备份任务。整个架构更新如下:
image.png
网友评论