用Flutter撸一个跨平台播放器App

仓库地址

Flutter开发项目的感受

一直从事移动端开发(iOS和Android),可能是对两端开发都熟悉的缘故,本人对跨平台一直是持谨慎甚至可以说是质疑态度的,因为真正做到跨平台很难。

这两年Google推出的Flutter一直也有去了解,但都是些零零散散的知识点,没有一个整体宏观的感受,最近就用项目来验证了一下开发细节和流程。

1. 开发思想上的差异

iOS和Android目前的主流技术还是命令式编程,而Flutter借鉴自React属于声明式编程

对于前端小伙伴来说Flutter的声明式编程很好理解,毕竟和React和Vue等框架都是类似的,我将声明式编程简单的理解为数据驱动的开发模式。

我们用一个列表的案例来体会一下:

iOS

UITableView通过从UITableViewDataSourceUITableViewDelegate获取数据和样式展示列表。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return _dataArray ? _dataArray.count : 0;
}

_dataArray数据改变后,UITableView是没法直接刷新的,需要调用手动调用UITableViewreloadData等方法:

[self.tableView reloadData];
Android

RecyclerView或者ListView通过Adapter获取数据进行列表的展示:

@Override
public final void onBindViewHolder(@NonNull VH holder, int position) {
    //...
}

@NonNull
@Override
public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    return onCreateHolder(parent, viewType);
}

@Override
public int getItemCount() {
    return _dataList.size();
}

_dataList数据改变后,RecyclerView是没法直接刷新的,需要调用手动调用AdapternotifyDataSetChanged等方法:

mAdapter.notifyDataSetChanged();
FLutter

ListView通过itemBuilder或者children获取Widget进行展示。

ListView.builder(
    scrollDirection: Axis.horizontal,
    itemCount: list.length,
    physics: ClampingScrollPhysics(),

    itemBuilder: (ctx, index) {
        return _buildTopItem(list[index])},
    )

list发生改变后,ListView会根据新的数据进行列表的刷新,无需显示调用刷新方法。

Vue

Vue使用的是模板语法,使用v-for将数据items展示为相应的HTML元素列表。

<div v-for="item in items" v-bind:key="item.id">
  <div>{
   
   {item.title}}</div>
</div>

items发生改变后,HTML元素列表会自动刷新,无需显示调用刷新方法。

  • Vue中有v-bind:key, Flutter中Widget的构造函数中也有key,其实都是借鉴于React的虚拟DOM,这个Key是起到diff时候进行对比来决定是否需要刷新的作用。

重点注意: iOS可以通过KVO将UI和数据进行绑定;而Google现在主推的JetPack也有DataBinding可以进行双向绑定。所以并不是iOS和Android开发没法进行声明式编程的开发,只是主流开发不是而已。

如果你有在原生开发上使用的有这些数据绑定的技术,那这里提到的命令式编程和于声明式编程的差异就可以跳过了。

2. 代码结构上的差异

现在的原生开发都比较青睐MVVM的架构,所以代码分层上来说是很清晰的。

但是我开发Flutter的感觉是代码的易读性和可维护性差一些。

Flutter中一切皆为WidgetWidget可以是展示的元素,例如:ListViewGridView, Image等;Widget可以是样式,例如:TextStyle, ThemeOpacity等;Widget也可以是事件,例如:GestureDetector,AbsorbPointer等;Widget也可以是数据和界面的组合体,例如:FutureBuilder,StreamBuilder等;总之,你想到的几乎所有的都是Widget。

由于借鉴了虚拟DOM来提高渲染效率,这些Widget组成了一个层层嵌套的树状结构,所以就形成了网友们调侃的嵌套地狱模式。一个界面有一个根Widget,然后所有的内容都在这根Widget下一步步嵌套下去。

例如:要实现如下的一个按钮,点击按钮跳转到播放页面

案例

理想的情况下需要嵌套GestureDetectorContainerText三层Widget,分别处理手势,控制大小和圆角、背景颜色,文字和样式。

// 点击的Widget
GestureDetector(
    onTap: () { print("跳转到播放页面"); },
    // 子Container
    child: Container( 
        width: 196.rpx, 
        height: 50.rpx,
        decoration: BoxDecoration(
        color: FBTheme.redColor,
        borderRadius:
            BorderRadius.circular(50.rpx)),
        alignment: Alignment.center,
        // 子Container
        child: Text( 
            "立即播放",
             style: TextStyle(
                color: Colors.white, fontSize: 30.rpx),
        ),
    ),
)

有的小伙伴可能会抽提Widget的方式进行代码复用和减少单个文件的代码量,但是这样又会增加数据传递和事件回调的复杂度。

3. 开发速度上的差异

Flutter在开发速度还是很快的,他的快速体现在两个方面。

  1. 一套代码可以实现跨平台的功能,所以相比开发iOS和Android两套代码速度上就快了很多。
  2. 开发FlutterHot Reload的功能,修改代码后保存一下代码就能看到修改后的效果。

这个功能iOS的小伙伴还是很羡慕的,每次修改iOS代码,都需要重新运行一下程序才能看到效果,即使熟悉各种LLDB调试技巧也是个很耗时的流程。而Android Studio推出的ApplyChange的功能还是很友好的。

4. 开发难度上的差异

iOSAndroid的原生开发的难度在需要熟悉对应平台的API,如果需要两个平台都开发那就接近双倍的工作量和难度了。原生开发实现各种需求功能还是没有太大的问题,对应平台的限制除外。

Flutter开发需要熟悉FlutterAPI,熟悉一套就可以跨平台开发了。

  • Flutter的文档和API还是非常详细的,甚至每个Widget都会有使用案例,这个对开发者是非常友好的。
  • 此外,Flutter封装的Widget非常丰富,甚至有些冗余。不需要寻求原生支持的情况下就能够满足绝大部分需求。

Flutter的难度在于开发者还是需要有原生开发的一些基础知识,这样在遇到问题时候能够很快速的解决问题,或者需要原生支持的时候写一些插件支持开发。

5. 执行效率上的差异

Flutter其实就是一个UI框架,基于Skia的图像渲染引擎进行绘制。由于Android本来就是基于Skia这个引擎,所以Flutter开发的应用在Android平台上和原生开发的性能相差不大。

FlutteriOS平台上其实是绕过了Core Text渲染引擎,而直接使用Skia引擎进行图像绘制,所以性能上也相差不大。但是由于需要引入Skia引擎,所以iOS包的体积会加大。

总结:

总体来说Flutter的开发体验和使用体验都还是很不错的。只要不触碰到苹果的一些利益和规则,这个跨平台方案能够有很大的发展空间。

Flutter实战项目介绍

我用Flutter撸了一个几乎完整的播放器App,一起学习,共同进步。

使用的技术包含但不限于:

  • 框架搭建
  • 网络请求
  • 应用主题
  • 动画实现
  • 事件总线
  • 页面路由跳转
  • 视频播放
  • 数据库的存储
  • SharePreference存储
  • 图片的适配
  • Iconfont的使用

部分界面

首页

频道

我的

我的喜欢

设置中心

意见反馈

搜索

播放

猜你喜欢

转载自blog.csdn.net/lcl130/article/details/114295865