目前市面上的Flutter都普遍用于一些简单页面,单纯铺设UI,而开眼快创作为完全使用Flutter开发的APP,除了简单的信息流页面,还有更重要的页面——视频编辑页面和模版视频制作页面。今天主要介绍一下开眼快创的视频编辑页面是如何生成和优化的。
在进入开眼快创项目之前,项目里有很多人甚至对Flutter是完全没有了解的,再加上当时市面上还没找到用Flutter写视频编辑页面的APP,因此很多技术方案都经过了漫长的摸索和迭代。
首先,熟悉一下开眼快创APP中视频编辑页面的基本样式(如下图):
视频编辑页面有主要以下几个特点:
-
状态复杂:有太多视频编辑的状态以及当前页面用户操作的中间状态等等。
-
技术复杂:跨端方案的多端数据类对齐和信息通信效率的提升。
-
逻辑复杂:变速的需求将时间对齐这件简单事情的复杂度提升了一个次元。
-
UI复杂:主要复杂在时间轴、视频轴、音乐轴以及音效轴等等。
-
性能要求高:预览播放时整个页面需根据播放情况更新对应状态,后续优化将主要针对这一点。
基于以上几个特点考虑,在技术方案确定之初,我们也考虑过视频编辑页面是否需要用原生来写,但是毕竟原生开发需要面临很多挑战。相比于市面上很多混编使用Flutter的APP来说,纯Flutter可以在Flutter侧统一管理资源,内存等,因此会避免很多混编的问题,所以我们决定统一都使用Flutter进行编写。
操作复杂性
由于该页面的状态较多,如果采用普通写法的话,把页面进行UI拆分后,各个Widget之间的耦合度会很高,为了解决这个矛盾,我们决定采用Redux处理。
Redux 和 setState
对于一般的StatefulWidget而言,当用户做了某些操作或当其它情况导致Widget中某些状态需要改变的时候,我们会调用setState重绘Widget,从而根据最新的状态展示UI,一般的StatefulWidget只管理几个状态。
而对于Redux而言,它有一个全局的AppState,可以将需要的State挂在这个AppState下,使用Redux的Widget可以提供一个View Model,Redux在属性改变的时候,会对比关心的View Model前后是否相等(所以Model的==方法需要根据开发者自身情况重写),不相等的时候重写会触发Builder方法进行重绘。
Redux的使用
我们创建了两个State:VideoEditorState和VideoEditorPageState。
VideoEditorState存储了VideoProjectWrapper,其主要用于管理当前正在编辑的视频项目的各种信息,例如添加了几个片段,每个片段需要截取哪段时间,倍速,加了多少音乐,音效字幕等等。
VideoEditorPageState就比较复杂了,当我们进行了几期迭代,但是当回过头再来看它的时候,发现它的状态已经多达40多个(篇幅问题不一一列举,如下图):
它主要存储了这个页面的各类中