如何学习flutter之flutter成神之路

为什么要使用Flutter?

为什么学习flutter是很多人的疑问,在我个人看来

  • 提高开发效率
    • 同一份代码开发iOS和Android
    • 用更少的代码做更多的事情
    • 轻松迭代
      • 在应用程序运行时更改代码并重新加载(通过热重载)
      • 修复崩溃并继续从应用程序停止的地方进行调试
  • 创建美观,高度定制的用户体验
    • 受益于使用Flutter框架提供的丰富的Material Design和Cupertino(iOS风格)的widget
    • 实现定制、美观、品牌驱动的设计,而不受原生控件的限制

作为一个零基础的同学。学习flutter无非就是从安装配置环境开始,这个是作为编程人员最基础的了,在这儿,记住一个地址:https://flutter.cn/

path 环境变量

如果你想在 Windows 控制台中运行 Flutter 命令,需要按照下面的步骤来将 Flutter 的运行文件路径加入到 PATH 环境变量。

  • 在开始菜单的搜索功能键入「env」,然后选择 编辑系统环境变量
  • 用户变量 一栏中,检查是否有 Path 这个条目:
    • 如果存在这个条目,以 ; 分隔已有的内容,加入 flutter\bin 目录的完整路径。
    • 如果不存在的话,在用户环境变量中创建一个新的 Path 变量,然后将 flutter\bin 所在的完整路径作为新变量的值。

运行 flutter doctor

安装 Android Studio或者VScode

我用 VScode,毕竟轻量化,这儿有几个插件值得推荐

  1. flutter
  2. dart
  3. Bracket Pair Colorizer 2
  4. Material Icon Theme
  5. Pubspec Assist
  6. Better Comments
  7. Gitlens
  8. Bonus: Move Bottom Panel to the side

Bonus: Move Bottom Panel to the side.

img
img

Right looks infinitely better.

Having the Panel at the bottom takes up a lot of space that you could use to read more code. Move your panel to the side instead (your code shouldn’t exceed 80 chars anyway) to use space more efficiently. Open Settings by hitting Ctrl + ,. Then, search for "Panel location". Change it from bottom to right.

这个时候环境搭建基本完成,就开始学习吧,学习flutter,建议首先看看dart语法相关的东西

高效 Dart 语言指南:API 设计

以及类型之间的相互转换,

List Set Map 还是要重点理解一下,

关于流程控制语句,if else while do while break container switch case 都是有必要的

接下来就是对dart 的一些库的了解

库重名的解决,as ,以及show 屏蔽其他,hide显示其他

学习完这些,再去学习flutter相关的,

相信很快就能做一款自己的app了,

flutter相关的,其实也就是一个widget的学习了,widget,分为两种

Flutter 中的自定义控件分为两类

  • StatelessWidget 无状态控件
    • 纯展示型控件,没有自己的私有数据和业务逻辑
  • StatefulWidget 有状态控件
    • 业务逻辑控件,可以定义自己的私有数据和业务逻辑

StatelessWidget 是无状态控件,没有自己的私有数据,是纯展示型的控件,基本定义过程如下:

class MyMidget extends StatelessWidget {
  // 构造函数:
  // 其中的 this.title 定义的是命名参数
  // @required 用来规定某个数据在初始化的时候是必须要提供的,否则会报错。
  MyApp({Key key, @required this.title}) : super(key: key);

  // final:用于修饰变量,表示单赋值(single-assignment),
  // 使用final修饰的变量必须进行初始化,一旦被赋值之后,不能够再次被赋值,否则编译会报错。
  final String title;

  // build 函数相当于 react.js 中的 render 函数
  // 必须 return 一个 UI 结构,用来构建当前控件对应的UI界面
  // 在 StatelessWidget 控件中,build 函数是必须的
  @override
  Widget build(BuildContext context) {
    return Text(title);
  }
}

基本使用过程如下:

void main() => runApp(
  // MyApp() 函数的调用,是 new MyApp() 的简写形式,
  // 其中 title 是构造函数的参数,
  // 且必须传递 title 数据,因为它已被标记为 @required 必填项
  MyApp(title: 'Flutter初体验鸭')
);

StatefulWidget 是有状态控件,这样的控件拥有自己的私有数据和业务逻辑,基本定义过程如下:

定义有状态的控件StatefulWidget

// 定义一个 电影详情 控件,继承自 StatefulWidget
class MovieDetail extends StatefulWidget {
  // 构造函数,初始化当前组件必须的 id 属性
  MovieDetail({Key key, @required this.id}) : super(key: key);

  // 电影的Id值
  final String id;

  // StatefulWidget 控件必须实现 createState 函数
  // 在 createState 函数中,必须返回一个继承自 State<T> 状态类的对象
  // 这里的 _MovieDetailState 就继承自 State<T>
  _MovieDetailState createState() => new _MovieDetailState();
}

定义继承自 State<T> 的状态类

// 这个继承自 State<T> 的类,专门用来定义有状态控件的 业务逻辑 和 私有数据
class _MovieDetailState extends State<MovieDetail> {
  // build 函数是必须的,用来渲染当前有状态控件对应的 UI 结构
  @override
  Widget build(BuildContext context) {
    // 注意:在这个 _MovieDetailState 状态类中,可以使用 widget 对象访问到 StatefulWidget 控件中的数据并直接使用
    // 例如:widget.id
    return Text('MovieDetail --' + widget.id);
  }
}

定义和修改私有数据

// 这个继承自 State<T> 的类,专门用来定义有状态控件的 业务逻辑 和 私有数据
class _MovieDetailState extends State<MovieDetail> {
  // 1\. 定义私有状态数据【以 _ 开头的数据,是当前类的私有数据】
  int _count;

  // 2\. 通过 initState 生命周期函数,来初始化私有数据
  @override
  void initState() {
    super.initState();
    // 2.1 把 _count 的值初始化为 0
    _count = 0;
  }

  // build 函数是必须的,用来渲染当前有状态控件对应的 UI 结构
  @override
  Widget build(BuildContext context) {
    // 注意:在这个 _MovieDetailState 状态类中,可以使用 widget 对象访问到 StatefulWidget 控件中的数据并直接使用
    // 例如:widget.id
    return Column(
      children: <Widget>[
        Text('MovieDetail --' + widget.id + ' --- ' + _count.toString()),
        RaisedButton(
          child: Icon(Icons.add),
          // 3\. 指定点击事件的处理函数为 _add
          onPressed: _add,
        )
      ],
    );
  }

  // 4\. 定义 _count 自增的函数【以 _ 开头的函数,是私有函数】
  void _add() {
    // 如果要为私有数据重新赋值,必须调用 setState() 函数
    setState(() {
      // 让私有数据 _count 自增 +1
      _count++;
    });
  }
}

两种状态的Widget学习完了,就是对其他的widget的学习了,

学习widget

只要记住在他的核心里面,万物皆可widget

我常用的也就是例如Container、Padding、Center、Align、Row、Column、Stack、ListView等也有上十种。

Flutter单节点布局控件功能分类:

对于这些,一定要会理解,会用,当然,前期的使用还是比较简单的。控件虽然这么多,但是大部分不会挨个去尝试。对于大部分人而言,都是佛系的用法,一个控件能够使用,就一直用到死。在布局上,大方向还是不停的,把一张设计图,拆成一棵树,每个节点根据需要,选择合适的控件,然后从根部开始不停嵌套,布局就完成了。到了后期,就不仅仅是页面的布局了,而在于对控件的选择

控件种类繁多,真正使用的时候该如何去选择呢?有万金油的做法,不管啥都用Container,这也是很多初接触的人经常干的方式。这么做的确可以按照设计图把布局给实现了,但是会涉及到一些性能上的问题。在我看来,控件的选择,按照控件最小功能的标准去选择。例如需要将子节点居中,可以使用Container设置alignment的方式,也可以使用Center。但是从功能上,Center是最小级别的,因此选择它的话,额外的开销会最小。将UI实现了,这只是最基本的,当达到这一步了,应该更多的去思考,如何更好的布局,使得性能更高。

而在我对于以下我称为多节点控件

  • 列表:GridView、ListView;
  • 单列单行或者多列多行:Row、Column、Flow、Wrap、ListBody、Table;
  • 显示位置相关:Stack、IndexedStack、CustomMultiChildLayout。

这几个空间还是应该学细一点,GridView、ListView、Row、Column、Stack,这几个控件基本上涵盖了大部分的布局了。所以更应该重点把握。

性能优化

刚才也提到,性能优化,关于性能优化,可能仁者见仁,并没有一个统一的说法,毕竟现在Flutter各方面都还不完善。但是,大方向还是有的,尽量使用功能集更小的控件,这个对于渲染效率上还是有所帮助的。

优化

在这里我试着去列举一些,并不一定都正确。

  • 如果一个布局多个控件都可以完成,则使用功能最小的,可以参照上面控件分类中的功能划分来做取舍;
  • 对于多节点控件,如果单节点控件满足需求的话,则去使用单节点控件进行布局;
  • 对于ListView,标准构造函数适用于条目比较少的情况,如果条目较多的话,尽量使用ListView.builder;
  • 对于GridView,如果需要展示大量的数据的话,尽量使用GridView.builder;
  • Flow、Wrap、Row、Column四个控件,单纯论效率的话,Flow是最高效的,但是使用起来是最复杂的;
  • 如果是单行或者单列的话,Row、Column比Table更高效;
  • Stack和CustomMultiChildLayout如果同时满足需求的话,CustomMultiChildLayout在某些时候效率会更高一些,但是取决于Delegate的实现,且使用起来更加的复杂;

上面所列的比较杂,但是归纳起来,无非这几点:

  • 功能越少的控件,效率越高;
  • ListView以及GridView的builder构造函数效率更高;
  • 实现起来比较复杂的控件,效率一般会更高。

选择

控件的选择,个人觉得把握大方向就够了。如果时间紧急,以实现效率最优先,如果时间充裕的话,可以按照一些优化细则,去做一些选择。单纯控件层面,带来性能上的改进毕竟十分有限。

可能需要组建的封装之类的了,良好的代码封装,你会发现可读性不仅好,还能提高编码的乐趣,所以我的目标就是写出诗歌一样的代码。

比如写一个登陆页面:

利用stack结合Positioned,实现相对定位,你就会发现,代码结构好看不说,也利于后期的维护

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      ///填充布局
      body: Container(
          width: double.infinity,
          height: double.infinity,
          //点击空白区域 隐藏键盘
          child: GestureDetector(
            onTap: () {
              _userNameFocusNode.unfocus();
              _passwordFocusNode.unfocus();
            },
            child: Stack(
              children: [
                //第一层 背景
                buildBackgroundWidget(),
                //第二层 气泡
                Positioned.fill(
                  child: BubbleWidget(),
                ),
                //第三层 高斯模糊
                buildFliterWidget(),
                //第四层 logo
                buildLogoWidget(),
                //第五层来个输入层
                buildInputWidget(context),
                //第六层 关闭按钮
                buildCloseWidget(context)
              ],
            ),
          )),
    );

这也仅仅是页面布局,后期很重要的就是与后端的数据进行交互了。在这个时候,或许用http也可以,但是还是强烈建议,利用dio

至于其他的一些插件,比如 shared_preferences,share,permission_handler,provider等等插件

之后对于Android和ios底层还要有一些理解,这样,对于个性化需求,也就不成问题了,学习是个漫长的过程,需要不断坚持,

后期我会结合我的学习,工作出一个系列,希望大家继续关注

我的系列内容主要包括

1.各个组建的用法,走一步,看一步,毕竟组件挺多的

2.我平时用到的三方插件,目前就有36种,我会出一个专栏

3.平时用到的一些经验,我会利用Demo进行演示

4.遇到的一些报错,以及解决方案

如果大家还有什么想看的,欢迎在评论区留言,就让我们一起利他共享,求实精进。

明天会出 一个提纲,大家的喜欢和点赞就是我最大的鼓励哦。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容