美文网首页FlutterFlutteriOS精品文章
基于Dart的新移动开发框架Flutter初探

基于Dart的新移动开发框架Flutter初探

作者: Hozan | 来源:发表于2018-04-08 15:36 被阅读906次

    前言:在2017年谷歌开发者大会上, Google展示了最新的开发者产品和平台,其中flutter和Material Design(纸墨设计)也被提及了。关于flutter新技术,笔者第一次接触,看了官网的一些基础部分和一些博客,特此在这做记录,有些引用到别人的地方会提供相关的链接,如果你也是做移动开发的,欢迎一起关注flutter,一起学习!

    一、Flutter简介和未来前景

    Flutter是Google使用Dart语言开发的移动应用开发框架,使用一套Dart代码就能构建高性能的iOS和Android应用程序(即App),并且在排版、图标、滚动、点击等方面实现零差异。

    Flutter简介:

    • 跨平台应用开发框架
      想象一下,一套代码可以同时跑安卓和苹果手机,而且性能跟原生一样,节省人力,提高开发效率,这一大亮点就足够吸引你去study。虽然reactnative(简称RN)也可以达到跨平台的目标,但是两者还是有所区别。后面会对Flutter和RN做一个对比。

    • 简单高效的Dart
      Dart语言是一种面向对象编程语言,跟其他面向对象编程语言差别不大,所以有java基础的入门没什么难度。谷歌选择Dart主要原因是:Flutter需要不断快速地创建和销毁短生命周期对象,Dart的垃圾回收机制非常适合用于完成这项任务。
      在Flutter里,界面布局直接通过Dart编码来定义,不需要使用XML或模板语言。

    • Flutter框架内置了一组丰富的设计控件
      一切皆控件,控件是每个Flutter应用程序的基本构建块,与分离视图、控制器、布局和其他属性的框架不同,Flutter具有一致的统一对象模型:控件。一个控件可以定义:结构元素(比如按钮或菜单)、风格元素(比如字体或颜色方案)、布局方面(比如填充)、一些业务逻辑等。

    • Flutter提供了热加载功能(Hot Reload)。

    • 支持Windows,Mac和Linux

    • 分层结构


      image.png

    Material层:根据Material Design设计规范开发的 Widget 库。这里的代码都位于 lib/src/material 目录下,里面包含了几乎所有 纸墨设计 规范里面定义的控件。比如 FloatingActionButton、BottomSheet 等。Material 层 是使用了 Widget 层的控件来构建的 。

    Widget层:定义了Flutter 框架的基础 UI 控件,比如 Text、Padding、ListView 、ImageView 以及事件处理等。Widget 层依赖下面的Rendering 层来构建的。

    Rendering层:绘制View视图。

    Engine层:Flutter能够在iOS和Android上运行起来,依靠的是一个叫Flutter Engine的虚拟机,Flutter Engine是Flutter应用程序的运行环境,开发人员可以通过Flutter框架和API在内部进行交互。

    Read More:https://blog.csdn.net/zhoumushui/article/details/79548075

    Flutter未来前景:

    对于flutter的未来前景,有些人看好,有些人不怎么看好,从我个人的角度看,一个新技术的诞生必定有它存在的原因和价值,毕竟,谷歌会耗费精力去开发flutter,未来它也许会颠覆移动开发,即使目前而言,移动开发已趋向于饱和。
    我比较看好flutter,因为它不仅仅是跨平台的开发框架,其响应式编程的思想也是一大亮点。以往的app开发方式显然存在某些弊端,才会出现新的技术框架来高效开发更优秀的应用程序。有些开发者接触flutter后,感觉其在性能方面更适合用于开发游戏,因为它帮你省掉了很多繁琐的工作。
    当然,flutter还很年轻,仍然在技术验证和研发阶段,目前没办法做到面面俱到。
    相关链接参考:

    二、Flutter和ReactNative的比较

    flutter在不久的将来应该会火,目前已经成为reactnative的竞争对手,下面对比一下flutter和reactnative这两者的优势和缺点。

    • react native的优势
      (1)比原生开发更为灵活和高效,对比h5的体验更好,性能方面接近原生。
      (2)可以远程调试代码,热加载
      (3)轻松实现热更新,可以在线更新代码
      (4)跨平台,实现一套代码跑安卓和ios移动设备
      (5)React Native实现不了的,可以通过原生来实现,可以互补
    • react native的缺点
      (1)即使是跨平台,但是不同平台的Api特性与显示不一定一致,有些组件的显示效果也是有平台方面的差异。
      (2)调试必须依赖于网络,如果没有网络是无法load js的代码。
      (3)增大了app的体积,reactnative集成了不少的插件和库,所以即使不怎么写代码,app也有十M左右
      (4)Android上的兼容性问题

    上面已经提及了flutter的一些情况,现在从下面几个方面对比这两者:

    • 性能和体验
      RN能达到60fps,而flutter实现120fps的渲染性能,所以流畅性,Flutter比RN好很多。
      和React Native一样,Flutter也提供响应式的视图,Flutter采用不同的方法避免由JavaScript桥接器引起的性能问题,即用名为Dart的程序语言来编译。Dart是用预编译的方式编译多个平台的原生代码,这允许Flutter直接与平台通信,而不需要通过执行上下文切换的JavaScript桥接器。编译为原生代码也可以加快应用程序的启动时间。

    Read More:https://blog.csdn.net/zhoumushui/article/details/79548075

    • 开发语言
      RN使用JavaScript,js是用于Web开发的脚本语言,通过js调用原生的UI组件必须经过一层桥接器。
      flutter使用dart语言开发,dart是一门面向对象编程语言,可以用于原生开发。
      这里不比较两门语言的优缺点,因为各取所需,适合才是最重要的。
    • 热加载
      RN和Flutter都能实现热加载,区别在于,如果使用真机调试的话,RN可以远程热加载,不依赖于数据线;Flutter要通过数据线连接上设备。
    • 维护成本
      原生开发的维护成本一直居高不下,所以才有这些跨平台框架的产生。
      RN开发效率高,维护成本相比于原生也降低了不少,而且懂web开发的人都可以很快入门RN开发。目前国内使用RN的人数很多。
      而对于flutter,必须要有一个学会Dart语言的开发者才可以去维护它,目前flutter的活跃量相比RN就少好多。

    三、Dart语言(https://www.dartlang.org/samples

    (1)每个app都有一个main()函数

    image.png image.png

    (2)声明一个变量

    在Dart代码的类型安全中,大多数变量不需要明确类型,因为有类型推断。


    image.png

    默认值:未初始化变量的初始值为null。即使具有数字类型的变量初始值也是空的,因为数字类型的变量也是对象。


    image.png

    在生产模式中,assert()调用被忽略。在“检查”模式下,除非条件为真,否则断言(条件)将引发异常。有关详细信息,请参阅断言部分https://www.dartlang.org/guides/language/language-tour#assert

    如果您不想更改变量,请使用final或const,而不是var,或者在类型之外使用。final变量只能设置一次;const变量是编译时常量。

    关于Dart语言的const和final的区别可以参考http://han.guokai.blog.163.com/blog/static/136718271201321911119331/

    关于Dart变量的使用可以看官网
    https://www.dartlang.org/guides/language/language-tour#variables

    JavaScript中为false的几种情况
    false,null,undefined,“”,0,NaN
    而Dart Code有所不同


    image.png

    (3)关键字

    image.png

    1 Words with the superscript 1 are built-in identifiers. Avoid using built-in identifiers as identifiers. A compile-time error happens if you try to use a built-in identifier for a class or type name.
    (ex:上标1的单词是内置标识符。避免使用内置标识符作为标识符。如果您试图为类或类型名使用内置标识符,则会出现编译时错误)

    2 Words with the superscript 2 are newer, limited reserved words related to asynchrony support added after Dart’s 1.0 release. You can’t use async, await, or yield as an identifier in any function body marked with async, async*, or sync*. For more information, see Asynchrony support.
    (ex:上标2的单词是较新的,有限的保留词,与在1版本发布后添加的异步支持相关。在任何标记为 async, async*, or sync*的函数体中,您都不能使用async,await,或yield作为标识符。有关更多信息,请参见 Asynchrony support
    (4)类class

    image.png

    四、Flutter开发环境搭建(windows系统)

    由于本人使用的是windows系统,下面介绍windows搭建flutter开发环境,如果你是mac,可以参考https://www.jianshu.com/p/a1344cfea21d

    1. 下载flutter SDK

    git clone https://github.com/flutter/flutter.git
    (注意要先安装git,如果未装的请自行百度安装教程)

    • 如果你没有翻墙,这里需要配置一下镜像服务器,要不然后面flutter doctor会一直失败
      在高级系统设置——环境变量加多两个环境变量:

    PUB_HOSTED_URL https://pub.flutter-io.cn
    FLUTTER_STORAGE_BASE_URL https://storage.flutter-io.cn

    image.png
    1. 在系统配置flutter的命令使其能全局使用,同样打开高级系统设置——环境变量,在Path变量中添加flutter的路径
    image.png
    1. 打开cmd窗口,输入
      flutter doctor
      这样它就会自动下载一些依赖库和基础控件


      image.png

      下载完成后:


      image.png
    2. VSCode配置【https://code.visualstudio.com/docs/?dv=win
      (这里也可以使用android studio3.0【http://rj.baidu.com/soft/detail/27390.html?ald】或者IntelliJ IDEA Community【https://www.jetbrains.com/idea/download/#section=windows】)
      输入flutter,New Project创建一个项目或者打开命令提示符,进入想新建flutter项目的文件夹下,输入:
      flutter create myDemoFlutter

    image.png



    相关网址推荐:

    五、Flutter开发一个demo App

    1. 按照以上教程运行一个helloworld的项目,代码和目录结构如下图所示:


      image.png

      用数据线连接上你的安卓设备,按F5即可运行app到手机上,运行效果如下图所示:


      image.png
    1. 热加载功能
      只要你在代码中修改了相应的布局,当你ctrl+s保存代码后,它会自动将修改的样式运行到手机app上,开发相当方便。
    2. 接下来开始撸代码,写一写简单的界面
      (1)首先看下图的代码,main函数采用了所谓的箭头函数写法,MyApp是继承至一个StatelessWidget类,然后重写一个build()方法,返回一个MaterialApp(即widget控件)。


      image.png

      官方解析:

    • 本示例创建了一个 Material app 。 Material 设计语言是一套移动设备和网页上的视觉设计标准。Flutter 提供了一套丰富的 Material Widgets 。

    • 该 app 继承了使它本身成为一个 widget 的 StatelessWidget 类。在 Flutter 中,大多数时候一切都可以看作 widget , 包括 alignment,padding 和 layout 。

    • Material 库中的 Scaffold widget 提供了默认的应用栏 (app bar),标题和构成主页面 widget 树结构的 body 属性。 widget 的子树可以非常复杂。

    • widget 的主要工作是提供一个build()方法,描述如何根据其他更低层级的 widget,来对这个 widget 进行展示。

    • 本示例的 widget 树由包含了 Text child widget 的 Center widget 组成。Center widget 可将它的所有子树对齐到屏幕中心。

    (2)下面根据官网写一个简单的例子,代码如下:
    import 'package:flutter/material.dart';
    import 'package:english_words/english_words.dart';

        void main() => runApp(new MyApp());
    
        class MyApp extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            return new MaterialApp(
              title: 'Startup Name Generator',
              theme: new ThemeData(
                primaryColor: Colors.blue
              ), //改变主题样式
              home: new RandomWords(), //定义子组件为有状态控件RandomWords的实例
            );
          }
        }
    
        class RandomWords extends StatefulWidget {
          @override
          createState() => new RandomWordsState();
        }
        //定义状态类RandomWordsState
        class RandomWordsState extends State<RandomWords> {
          final _suggestions = <WordPair>[]; //用于保存随机字符串词组
          final TextStyle _biggerFont = new TextStyle(fontSize: 18.0);//字符串的样式
          final _saved = new Set<WordPair>(); //保存选中的值
    
        void _pushSaved(){
          Navigator.of(context).push(
            new MaterialPageRoute(
              builder: (context){
                final titles=_saved.map((pair){
                  return new ListTile(
                    title: new Text(
                      pair.asPascalCase,
                      style: _biggerFont,
                    ),
                  );
                });
    
                final divided=ListTile.divideTiles(
                  context: context,
                  tiles: titles
                ).toList();
    
                return new Scaffold(
                  appBar: new AppBar(
                    title: new Text('Saved Word'),
                  ),
                  body: new ListView(
                  children:divided,
                  ),
                );
              },
            )
          );
        }
          @override
          Widget build(BuildContext context) {
            return new Scaffold(
              appBar: new AppBar(
                title: new Text('ListView'),
                actions: <Widget>[
                  new IconButton(icon: new Icon(Icons.list),onPressed: _pushSaved),
                ],
              ),
              body: _buildSuggestions(),
            );
          }
    
          Widget _buildSuggestions() {
            return new ListView.builder(
              padding: const EdgeInsets.all(16.0),
          //通过ListView自带的函数itemBuilder,向ListView中塞入行,变量 i 是从0开始计数的行号
         //此函数会自动循环并计数
              itemBuilder: (context, i) {
                if (i.isOdd) return new Divider(); ////奇数行塞入分割线对象
    
                final index = i ~/ 2;
                if (index >= _suggestions.length) {
                  _suggestions.addAll(generateWordPairs().take(10));
                }
                return _buildRow(_suggestions[index]);
              },
            );
          }
    
          Widget _buildRow(WordPair pair) {
            final hasSaved = _saved.contains(pair);
          //ListTile和Text都是material.dart中的基础控件
            return new ListTile(
              title: new Text(
                pair.asPascalCase,
                style: _biggerFont,
              ),
              trailing: new Icon(
                hasSaved ? Icons.favorite : Icons.favorite_border,
                color: hasSaved ? Colors.red : null,
              ),
              onTap: () {
                setState(() {
                  if (hasSaved) {
                    _saved.remove(pair);
                  } else {
                    _saved.add(pair);
                  }
                });
              },
            );
          }
        }
    

    效果图如下:


    image.png



    相关链接:

    六、调试和性能监测

    官网关于debug app的链接可以查看https://flutter.io/debugging/
    Flutter Widget Inspector是用于可视化和探索Flutter Widget树的强大工具,官网对于该工具的说明可以查看此链接
    http://doc.flutter-dev.cn/inspector/
    需要说明一点的是只有Android Studio和IntelliJ IDEA两个工具适用,VSCode没有这个功能。

    image.png

    下面以AS3.0开发工具说明一下该功能:

    • 首先要在AS下载相应的插件,比如Dart和Flutter。
      点击FIle-Settings打开Plugins,搜索dart和flutter,安装好相应的插件


      image.png

    这里安装这两个插件好像要翻墙,所以要科学上网,如果你不能翻墙,可以跟我要Dart和Flutter插件库,通过本地来安装。

    • 安装好之后重启android studio,新建一个FLutter Project,然后运行App


      image.png
    • 最后打开Flutter Inspector可以查看Widget和Render Tree


      image.png
    image.png

    点击Toggle Select Widget Mode,再点击app上的每个布局控件,可以查看相应的属性和值。

    • 打开Android Profiler可以查看CPU和MEMORY的一些使用情况


      image.png

    通过AndroidStudio来开发和调试也是相当方便的,只是对于电脑的性能要求有点高,VScode编辑和开发比较轻便,但是调试方面没有AS好。

    相关网址推荐

    1、flutter中文官网http://doc.flutter-dev.cn/setup-windows/

    2、flutter英文官网https://flutter.io/setup-windows/

    3、Dart官网https://www.dartlang.org/

    https://www.dartlang.org/guides/language/language-tour

    Dart语言入门博客推荐;http://han.guokai.blog.163.com/blog/static/1367182712012101293119173/

    4、flutter开发者社区http://flutter-dev.cn/

         flutter圈子https://www.jianshu.com/c/ebc9d2e84214

    5、开源项目学习

    (1)https://github.com/Yonkers/flutter_wan_android

    (2)http://flutter-dev.cn/topic/58/kindle-%E7%AE%80%E6%8A%A5

    (3)https://github.com/heruijun/flutter_boss

    6、学习视频

    (1)https://www.bilibili.com/video/av14430321/

    (2)https://www.bilibili.com/video/av6269773/

    (3)https://www.bilibili.com/video/av20836069/

    7、关于flutter

    http://www.sohu.com/a/130790381_487499

    http://blog.chengyunfeng.com/?p=1033

    http://www.infoq.com/cn/articles/why-flutter-uses-dart

    相关文章

      网友评论

      • 羽纱:要是能补上debug,ui调试,性能监测就更好了
        Hozan:@羽纱 好,我一定补上

      本文标题:基于Dart的新移动开发框架Flutter初探

      本文链接:https://www.haomeiwen.com/subject/yreycftx.html