Flutter组件化框架-飞
发布时间: 2023-07-06
组件化无处不在

军队中有“军师旅团营”,营是团的组件,师是军的组件。

国家中有“省市县乡村”,村是乡的组件,市是省的组件。

要管理复杂的结构,逐层划分组件是一个很好的方法。

本文探讨的组件化,并非以代码复用为目的。

本文关注于通过组件化,管理比较复杂的工程,提高人效,降低损耗。

问题

复杂的工程往往存在如下两个主要问题:

    代码量大编译慢。逻辑复杂难维护。
解决思路化整为零

说到代码风格,很多人都知道这个常识。

如果一个函数太长了,需要拆成不同函数。

如果一个类太长了,需要拆成不同类。

如果一个文件太长了,需要拆成不同文件。

同样的,如果我们的项目太大,文件太多,就需要拆分成不同的组件了。

减少耦合

如果拆成不同组件后,各个组件仍然有千丝万缕的联系,维护起来仍然会一团乱麻。

我们应当尽量避免组件之间的依赖。减少耦合。

利用router可以很好的解决页面互相跳转时引起的耦合。

后面将会演示如何在flutter中实现通过路由减少耦合。

怎样组织你的代码大军

之前见到过一套Android代码“充分”利用了MVP模式。 整个项目下面分了3个目录,M,V,P。 V下面又分 Activities,Views,Adapters,...

虽然逻辑和UI分的很开,但是要修改一个业务或者新加一套功能,需要跨越各个目录,逐一添加代码。

我比较推荐的是下面的划分方法:

+------------------------------------------------+|                    main frame                  ||  +-----------+-----------+-----------+-----+   ||  | business1 | business2 | business3 | ... |   |+--+-----------+-----------+-----------+-----+---++------------------------------------------------+|                   common                       |+------------------------------------------------+复制代码

business1,business2,business3,...是不同的业务模块。

例如: 画廊,搜索,课程,推荐,....

这样做的好处是,当你添加代码的时候可以专注于当前业务, 忽略其他业务模块,大大减小了需要维护的代码的范围。

通常产品需求的发展和变化也是按照业务为单位进行的。 比如产品经理想到了一种新的课程模式,这个需求将影响到和课程相关的一些代码。 如果我们的代码本来就已经将课程业务封装在一起的话,修改将都在这个模块内部进行。而不会株连其他部分的代码。

当然我们不是不考虑代码的复用,通常有很多值得复用的代码都是和业务无关的。 和业务无关,也就是说不专属于某个业务,业务A可能会用到,业务B也可能会用到。 这些可复用的业务无关的代码将会方阵上面架构的common部分。

总结一下:
    以业务模块作为最基础的代码划分,将业务变化隔离在相应的组件内部。主框架和业务模块都依赖的部分,放入公共库。(公共库中都是业务无关代码)
Flutter中的实践

Flutter天生就适合组件化,只要你研究的足够深入,就能发现这些特征:

    自带工具可创建独立运行组件 (modules)自带路由支持 (router)可通过命令行环境变量区分app和组件运行环境(commandline env)

在这里我专门写了一套框架示例: Flutterame

命名含义:Flutterame = Flutter + Frame

准备

工欲善其事,必先利其器。

让我们先准备一下.

1. 创建工程

flutter create --org top.ovo --platforms ios,android flutterame

想要学习flutter create的更多用法可以看一下我的另一篇文章:玩转flutter create命令,做10倍程序员 其中除了我对 flutter create --help的翻译还有一些其他的奇怪的小技巧。

2. 针对国内网络优化Android编译速度2.1 手动修改android/build.gradle文件。

修改前:

    repositories {        google()        jcenter()    }复制代码

修改后:

    repositories {        maven { url 'https://maven.aliyun.com/repository/google'} // google()        maven { url 'https://maven.aliyun.com/repository/jcenter'} // jcenter()    }复制代码
2.2 用脚本修改
bin/optimize_cn_network.py android/复制代码

网速优化详情见:Flutter工程的Android编译网速优化

好了这下你可以愉快的flutter run了。

准备工作完成,接下来我们创建一个组件。

开始实现组件化3. 创建组件

假如我们要在项目下的modules/目录下创建名为gallery的模块,我们可以先进入modules目录再用flutter create创建模块

flutter create -t module --org top.ovo gallery复制代码

这里的-t module表示要创建的是一个组件而不是完整的app。

创建的组件目录如下:

.├── .android├── .dart_tool├── .gitignore├── .ios├── .metadata├── .packages├── README.md├── build├── gallery.iml├── gallery_android.iml├── lib│   └── main.dart├── pubspec.lock├── pubspec.yaml└── test复制代码
3.1 组件可以直接运行

在当前组件目录中,我们可以直接用flutter run 运行这个组件。 不久你就能看到熟悉的计数器demo页面。 它和一个普通的app没有太大区别。

由此可见,Flutter的开发者充分考虑到了组件化的需求。你不但可以把组件放在app中运行,也可以单独运行组件。

3.2 神奇的“.android” 和 “.ios”

如果你仔细观察创建好的目录,你会发现一个有趣的现象:

在app中android和ios目录不见了。取而代之的是两个隐藏目录 “.android” 和 “.ios”。

也就是说这两个目录是隐藏的,默认情况下是不会被添加到git中的。 那如果其他人拉取了这套代码,还能单独运行这个组件吗?

经过实验发现:

如果在没有“.android” 和 “.ios”目录的组件目录中运行flutter run的时候。

Flutter会重新创建“.android” 和 “.ios”目录。

正因为.android目录是代码生成的,你在里面所做的一切修改,随时可能会被丢弃。 因此在我的Flutter工程的Android编译网速优化一文中还介绍了脚本自动优化网速,以免除每次手动修改的麻烦。

创建完组件就该使用了,接下来我们一起看看如何使用组件代码。

3.3 在app中嵌入你的组件界面。3.3.1 创建组件界面

首先我们创建一个简单的组件界面Galleria,将其存放在组件的gallria.dart文件中

modules/gallery/lib/gallria.dart:

import 'package:flutter/material.dart';class Galleria extends StatelessWidget {  const Galleria();  @override  Widget build(BuildContext context) {    return Center(child: Text("Galleria"));  }}复制代码
3.3.2 app中添加对组件对依赖

我们的app要调用组件中的代码,需要先声明对组件的依赖:

我们可

微信