使用RxSwift上传多媒体帖子

我们的App有一个很重要的功能是,上传潜水日志。一则潜水日志的内容除了一般的文字内容之外,还可以包含图片,影片等多媒体消息。

原始工具

原本的上传程序码实作在一个显示上传进度的画面中,前后将近三千行。更新画面的程序与异步API调用关联在一起,结果就是发生问题不容易跟踪/调试,不易做画面调整,多-线程调整,也不容易做错误处理。而原始使用条件锁来确保程序的前后关连性,循序加载的结果也造成速度慢,无法有效利用手机及网路的效能。

需求分析

  • 一则Divelog可能包含多张照片,影片,影片需要上传缩图。
  • 多媒体档案需先上传到AWS S3
  • 多媒体档案上传成功后将URL组入divelog对象再调用API上传Divelog
  • 若上传有失败就不要继续往下做
  • Divelog上传完毕还有两个后处理的API要调用
  • 需要在画面显示上传进度
  • 发布成功要删除一些缓存的资源
  • 未来还有离线发布/定期上传Divelog的需求
  • 未来重建发布Post画面时也希望可以重用UploadTask

重点:各照片/影片的上传之间没有前后关连性,但希望可以在全部上传完成之后再做后续动作。

既然有这么多上传动作要完成,又需要各别状态与进度。我先做了一个UploadTask的基类:

一个DivelogPost的UploadTask实际上包含n张照片的UploadTask以及,如果有video的话,需要一个UploadTask上传video本身,以及一个UploadTask负责上传缩小图。流程看起来像这样:

使用RxSwift CombineLatest将这些任务的行为整并在一起,等全部都完成了再往下打PostAPI跟后续的处理。

中间的任何一个任务有错误,都可以送错误出来。如此也可以把错误处理统整在一起处理。

技巧

  • PublishSubject需先送一个初始值出来,不然progress不会开始跑。
  • 可以写个FailTask​​测试错误流程

想清楚之后写起来其实很快,纠正之后流程就相当清楚,也不容易发生哪一条路的错误处理漏掉,让画面挂住无法继续使用的状况。

  1. 发布流程清楚明了,与画面解构。
  2. 各UploadTask对象可在其他需要上游的地方重用。
  3. 易于将上传进度更新到画面。
  4. 容易处理错误状态。
  5. 未来实作离线发布功能时,实作从离线返回在线状态,实作多篇文章发布上传也很简单。需要平行或循序上传也容易切换。
  6. 未来重建一般帖子上传介面时,也可直接重用PostUploadTask

这整体上传流程开发完成后,虽然没能够在短时间之内应用到专案内所有上传。但当后续要替换其他地方的上传行为,甚至也不必由自己进行开发,交给其他同事也都能够轻易接手实作。

其他可以再improve的地方

  • 或许改用协议而非基类?
  • 以操作实作
  • 将progress与status合并为同一个PublishSubject

当初在定义UploadTask的基类时,并没有特别想到什么,只是有个感觉就开始做了。定义了类。或许下回再实作时可以再好好回顾一下Operation的其他特性。

这也是我第一次尝试使用RxSwift。重点在使用可观察的模式以及利用最新的管控流程,整体来说写起来还蛮简洁的,并没有用的多么流利或与一般实作有多不同。范围小心使用,尽量不要为用而用的无限扩张下去。