便利贴 App 专案介绍

Screenshot

https://user-images.githubusercontent.com/7949400/124440143-e457ba00-ddac-11eb-93f4-1d3470001528.gif

专案介绍

相信大家都有用过便利贴吧!在开会讨论时便利贴是一个很好用的工具,不同的颜色可以代表不同的分类方式,在便利贴上也可以写字、画图,另外还可以移动便利贴的位置来做一些整理。以下是这专案的基本需求:

专案需求

  • 使用者可以任意新增、删除便利贴。
  • 使用者可以编辑便利贴上的文字以及背景颜色。
  • 使用者可以使用手势任意拖拉便利贴的位置。
  • 可以与其他使用者一起线上编辑。

需求分析

这不是一个典型的 Mobile app ,我所谓的典型指的是可以使用 Android 内建元件来构建出整个 App 的版型,在这个 app 中,除了 Float Action Button,跟一些简单的按钮除外,我们必须要想办法画出这个 app 的核心 - 便利贴。

除此之外,线上共同编辑也是一个非常具有挑战的点。如果使用 Restful api 呼叫的话,这个 app 会发生什麽事呢?由於这会是一个非常需要即时回馈的系统,在一分钟也会执行非常多次的操作,所以一分钟内光是一个使用者就有可能发出 30 个以上的 api 请求,每一个 api 请求会带有很多的资讯像是 header、access token、JSON 等等, 这对 Server 会是一个很大的负负担!同时,後端的资料库也会有大量的读写需求,更何况还有排队以及延迟的问题,有非常多的技术问题要被解决。但其实说了这麽多,後端也不是我的战场,以上这些是依我的个人过往的经验所能想得到的问题,说不定在扩大规模後又有更多更难解决的问题。

最後,在手势拖拉的部分,我可以预期到的是,便利贴的位置是每一分每一秒都在改变的,而这个特性正好适合使用 Reactive programming 的方式来处理,Reactive programming 就是一个处理非同步事件流(Asynchronous event stream)的编程方式,而便利贴在某个时间点中的位置就可以当作是一个事件,一个单一手势的位置,也可以是一个事件。因此当手势的事件连在一起变成一个事件串流时,就可以利用这个事件串流产生出便利贴相对应的位置。除此之外,还有许多 Reactive programming 使用上的好处,关於 Reactive programming ,在後面的文章中会有更详细的介绍。

技术选择

View

其实大家应该都知道我选择什麽技术了,因为标题已经写的很明显了,但是我还是要假设一下,如果使用传统的 Android View 来做这个便利贴 App ,会怎麽做?

如果使用大家最熟悉 xml 的话,有办法完成这个 App 吗?很可惜的是动态的 UI 元件不是 xml 的强项,所以中间的这些便利贴无法使用单纯的 xml 。所以下一个明显的选项就是自定义 UI 元件 (Custom View),在这里我想到以下两种方式:

  1. 一个 View group + 多个 View ,每一个 View 就是一个便利贴。
  2. 一个 Custom View ,其中全部的便利贴都是使用 Canvas 跟 paint 画出来的。

第一种方法的话,如何处理手势的事件将会是一大挑战,是要全部交给 View group 来处理呢?还是每个 View 各自处理?全部交给 View group 来处理的话就必须要有方法能够知道现在的手指是不是有碰到哪一个便利贴,而且这些便利贴还有可能重叠,这就会需要一些数学计算了。那如果手势处理交给每一个 View 自己来做呢?看起来比较可行,但是要如何将位置资讯传出去呢?毕竟这些座标资讯还是要传给後台才能让其他使用者看到对吧?所以每一个 View 都可能会需要一个 callback 来处理这些事件,这样做的话可能也要小心不要产生 memory leak。

再来是第二种方法,这个方法看起来弹性很大很自由,但是取而代之的就享受不到 Android 帮你做的绘图优化,像是每次画面更新就是整个画面一起画,第一种方法的话,只要每个 View 自己呼叫 invalidate() 就好,不会影响到其他在同一个 View group 的 View,所以效能上可能会比较差。再来绘制顺序也要自己管理,因为再也没有内建的 z 值可以保证显示的顺序。但是相对的,要在这个 View 里面设计架构时就不会有太多限制,不会有 framework 来限制你手势管理还有便利贴与整个画面之间的交互关系。

invalidate: 这是 Android View 中的一个公开函式,呼叫这个函式之後,这个 View 所绘制的内容就会强制更新到最新状态。

那 Jetpack Compose 呢?他能很简单的解决上述的很多问题,包含绘制上的优化,元件之间的互动关系等等,甚至还有 Preview 可以让你不用 Build app 也可以直接看到结果长怎样。那缺点呢?怎麽可能没缺点呢?缺点就是,虽然程序码看起来简单,但是不是很容易就可以学得起来,学完一整套到能够实际上战场要花相对多的时间。

不过现在拉回来以这个专案来说,由於我已经研究 Jetpack Compose 有一段时间,所以这对我来说学习不是一个阻碍,但如果这专案还有其他成员的话可能就要先想想,如果有很多 junior developer,就不会是个好选项。

Backend

後端的部分,使用 Firebase Firestore 是一个非常棒的选择,首先我不需要花很多时间去建立一个 Server,而且 Firestore 这种 NoSQL 的方式也非常适合我这个 App 的特性,firestore SDK 使用上也非常简单,关於更详细的内容,我会在之後一起介绍。

Reactive

Reactive programming 现在有几个主流的函式库,我将会直接采用他们中的其中一个,自己打造轮子不是聪明的作法。主要的选项有:

  1. RxJava
  2. Coroutine Flow

在这边我放弃使用潮潮的 Coroutine Flow ,因为前阵子在 side project 使用时,还是有部分的 Api 是 Experimental 的,所以依我看来还没有 RxJava 那麽的成熟稳定,还有一个非常重要的点,就是我对 Flow 非常的不熟,很多我在 RxJava 能够轻易做到的事,可能要在 Flow 上试错不少次才能找到相对应的作法。

小结

以上就是这专案的介绍以及技术的选择,技术的选择上没有绝对的对错,团队的组成、需求、对工具的熟悉程度都会是影响的因素。但是在技术的选择上,要尽量避免盲目的追求最新潮流,很多工程师都会很喜欢做这件事(也包含我),如果我在这专案的选择是 Coroutine Flow 而不是 RxJava 的话,我可以预见的是可能带给读者很多错误的资讯,而且想要花最多心力写的知识内容也会因此而降低质量,不是我想看到的结果。


<<:  WordPress 如何引用 Bootstrap 的 CSS 及 JS 档案制作精美画面

>>:  [DAY 02] Google Apps Script

广播推送 - day24

目标 从左画面将讯息推送到右边画面,嗯! 就这样。 本示例从主画面推送讯息,其他开启本网的使用者无论...

Swift纯Code之旅 Day26. 「客制化Switch按钮」

前言 我们可以到Switch开启时背景色会是绿色,关掉时却是黑色,这样其实跟原本IPhone内建的也...

[Day 24 - Modern CSS] 在JS中写CSS,神套件Styled-components

要如何在 React 中撰写 CSS,为元素添加样式?目前的方法有 Inline-Style、CSS...

[前端暴龙机,Vue2.x 进化 Vue3 ] Day25. Vue3 Composition API 使用(一)

在 Composition API 当中我们可以将响应式资料和相关业务逻辑结合到一起,是因为 Vue...

Swift纯Code之旅 Day5. 「编辑与新增 - Navigation Bar」

大家应该还记得昨天我们有说到今天会聊聊TableView Cell的内容,事不宜迟, 马上来聊聊N...