目录

flutter build和assemble区别 flutter和flap区别_Dart

  • 参考文章
1.Flutter是什么?
  • Flutter是Google papa推出的一款全新的,响应式·跨平台·高性能的移动开发框架。
2. Flutter与其他框架对比
  • 在移动开发的中的跨平台中有以下几种方案:
  • 基于WebView 和JavaScript(Cordova,AppCan)
  • 基于HTML和JavaScript渲染映射成原生控件(ReatNative、Weex)
  • 基于微信生态的小程序
  • 基于原生编码无桥接(Flutter)

方案

优点

缺点

基于WebView和JavaScript的方案(Cordova)

1. 可以继承Web开发的所有成果

(丰富的控件库,满足各种需求的页面框架,完全动态化,自动化测试工具等)

2.学习成本低(不需要太多的成本和迁移成本就可以开发一个app)

1.WebView渲染效率和JavaScript的执行性能太差

2.由于Android各个系统版本和厂商的定制,很难保证在所有设备有一致的效果

基于HTML(vue)和JavaScript渲染映射成原生控件(ReatNative,Weex)

1.将渲染工作交给原生,性能体验好

2.Facebook出品推出时间较长,社区资源丰富

随系统版本变化和API的变化,需要处理不同平台的差异,有的特性不能满足所有平台(第三方库良莠不齐,维护困难)

基于微信生态的小程序

1.迭代速度快,学习成本低

2.可以实现动态无缝更新,可以利用微信强大的用户基数

依赖于微信产品生态,定制程度大打折扣

基于原生编码无桥接的Flutter

1.热重载

2.渲染引擎依赖跨平台的Skia图形库(一个开源的2D图形库在一系列硬件和软件平台提供通用的API),可以最大程度保证不同平台和设备的体验一致性

3.使用支持AOT的Dart语言,执行效率比JavaScript好很多

4.美观可定制的组件

1.dart 语言的生态小,精通成本比较高

2.嵌入外部 platform view 成本高这块(基于官方代码)目前在 iOS 端有支持,android 上还没有,但相关开发者博客上有提到实现了webview,mapview 等 platform view 的嵌入。从 iOS 端的实现来看,每嵌入一层 platform view 会额外多一层 surface,内存代价比较高

3.flutter 目前提供的开箱即用的功能只有 UI framework + dart 语言的能力,平台能力需要通过 platform channel 来扩展。(目前丰富的程度有限,未来可期

3.Flutter的Dart架构和Dart语言
  • Flutter的框架部分全部完全使用Dart语言实现,有着清晰的分层架构。分层架构使得我们可以在调用Flutter提供的便捷开发功能之外,还可以修改每一层额实现Framework的底层是flutter引擎,引擎主要负责图形绘制(skia),文字排版(libtxt)和提供Dart运行时,引擎全部使用C++实现,Framework层使我们可以用Dart语言引擎的强大能力.
  • flutter build和assemble区别 flutter和flap区别_flutter_02


  • flutter build和assemble区别 flutter和flap区别_flutter_03

  • Dart部分的最低层为Foundation其中大都是非常基础的,提供给其他所有层的工具类和方法。
    绘制库(Painting 封装了Flutter Engine 提供的绘制接口,主要是为了在绘制控制等固定样式时提供更直观,更方便的接口,比如绘制缩放后的位图,绘制文本,插值生成阴影以及在盒子周围绘制边框等。
    Animation动画类提供了类似Android系统的ValueAnimator的功能,并且提供了丰富的内置插值器。
    Gesture手势类提供了手势识别相关功能,包括触摸事件类定义和多种内置的手势识别器。GestureBinding类是Flutter中处理手势的抽象服务类,继承自BindingBase类。

Binding系列的类在Flutter中充当类似于Android中的SystemService系列(ActivityManager,PackageManager)功能,每个Binding类提供一个服务的单例对象,App最顶层的Binding会包含所有相关的Binding抽象类。如果使用Flutter提供的控件开发,则需要使用WidgetsFlutterBinding,如果不使用Flutter提供的控件而直接调用Render层,则需要使用RenderingFlutterBinding。

  • 渲染库(Rendering)
  • Flutter的控件在实际显示时会转换成对应的渲染对象(RenderObject)树来实现布局和绘制操作。一般情况下,我们只会在调试布局,或者需要使用自定义控件来实现某些特殊效果的时候,才需要考虑渲染对象的细节。渲染库主要提供的功能类有:
    (对于mixin的Dart语言机制可以参考Flutter基础:理解Dart的Mixin继承机制
/// The glue between the render tree and the Flutter engine.
//RendererBinding是渲染树和Flutter引擎的胶水:负责管理帧重绘,窗口尺寸和渲染相关变化的监听
mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, SemanticsBinding, HitTestable {
}
/// RenderObject渲染树中所有节点的基类,定义了布局,绘制和合成相关的接口
abstract class RenderBox extends RenderObject {
}
/// An image in the render tree.
class RenderImage extends RenderBox {
}
/// A table where the columns and rows are sized to fit the contents of the cells.
class RenderTable extends RenderBox {
}
/// Displays its children in a one-dimensional array.
class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox, FlexParentData>,
                                RenderBoxContainerDefaultsMixin<RenderBox, FlexParentData>,
                                DebugOverflowIndicatorMixin {
                                }
 /// A render object that displays a paragraph of text
class RenderParagraph extends RenderBox {
}
  • 在Flutter界面渲染过程分为三个阶段:布局,绘制,合成,其中布局和绘制在Flutter框架中完成,合成交由Engine负责
  • UI绘制流程
  • 1.运行动画,动画的结果会导致 Widget State 的改变;
  • 2.State Changes 触发 Flutter 生成一棵新的 Widget 树;
  • 3.Flutter 根据新/旧 Widget 树的差异更新 Render 树,重新排版更新界面布局;
  • 4.Flutter 根据新的 Render 树更新 Composited Layer(合成图层)的 Display List;
  • 5.输出新的图层树;
  • Widgets库
  • Flutter提供了非常丰富的控件,包括最基本的文件,图片,容器,输入框和动画等。在Flutter中“一切皆是控件”,通过组合,嵌套不同类型的控件可以构成任意功能,任意复杂度的界面,以下为widget库中重要的几个类:
WidgetsBinding是widgets 层和Flutter引擎的胶水层

flutter build和assemble区别 flutter和flap区别_flutter_04


flutter build和assemble区别 flutter和flap区别_Dart_05

  • Widget就是所有控件的基类,它本身的所有数据是只读的。RenderingObjectWidgets所有的实现类负责提供配置信息并创建具体的RenderObjectElement。widget的属性最好都是immutable。
  • Element是Flutter用来分离控件和真正渲染对象的中间层,控件用来描述对应的element属性,存放上下文,通过Element遍历视图树,Element同时持有Widget和RenderObject。控件重建后可能会复用同一个element。RenderObjectElement持有真正负责布局,绘制和碰撞测试(hit test)的RenderObject对象。
  • RenderObject:根据Widget的布局属性进行layout,paint Widget传入的内容。
  1. 为什么widget都是immutable?
    flutter界面开发是一种响应式编程,主张simple is fast,flutter设计的初衷希望数据变更时发送通知到对应的可变更节点(可能是一个StatefulWidget子节点,也可以是rootWidget),由上到下重新create widget树进行刷新,这种思路比较简单,不用关心数据变更会影响到哪些节点。
    2.widget重新创建,element树和RenderObject树是否也重新创建?
    widget只是一个配置数据结构,创建是非常轻量的,加上flutter团队对widget的创建/销毁做了优化,不用担心整个widget树重新创建所带来的性能问题,但是RenderObject就不一样了,RenderObject涉及到layout、paint等复杂操作,是一个真正渲染的view,整个view 树重新创建开销就比较大,所以答案是否定的。
  • Dart语言
  • Dart语言的重要理念
  • 放在变量中的所有东西都是一个对象,每个对象都是一个类的实例。即使是数字,功能, null也是对象。所有对象都从Object类继承。
  • 虽然Dart是强类型的,但类型注释是可选的,因为Dart可以推断类型。在上面的代码中,number 被推断为是类型的int。当你想明确地说没有类型时, 使用特殊类型dynamic。
  • Dart支持泛型类型,如List(整数列表)或List(任何类型的对象列表)。
  • Dart支持顶层函数(如main()),以及与类或对象绑定的函数(分别为静态方法和实例方法)。你也可以在函数中创建函数(嵌套函数或局部函数)。
  • Dart支持顶级变量以及绑定到类或对象(静态变量和实例变量)的变量。实例变量有时称为字段或属性。与Java,dart不具备关键字public,protected和private。如果标识符以下划线(_)开头,则它的库是私有的。有关详细信息,请参阅 库和可见性。
  • 标识符可以以字母或下划线(_)开头,然后是这些字符和数字的任意组合。有时候,重要的是某件事是一种表达式还是一种 声明,所以这两个词的确切含义很有帮助。
  • Dart工具可以报告两种问题:warnings 和errors。警告只是表明您的代码可能无法正常工作,但它们不会阻止您的程序执行。错误可以是编译时或运行时。编译时错误导致代码无法执行; 运行时错误导致 代码执行时引发异常。
  • Dart语言入门
4.Flutter 初体验
  • Flutter纵使千般好,纸上得来终觉浅。按照官网下载了Flutter SDK,使用Android Studio 3.3.2,使用了Github的下列教程代码 awesome-flutter的FlutterWhatsAppClone项目
  • pubspec.yaml
  • 依赖配置声明文件
#在Flutter中,依赖包由Pub仓库管理,项目依赖配置在这个文件中声明即可,
	#对于未发布在Pub仓库的插件可以使用git仓库地址或文件路径
	name: flutterwhatsapp
	description: A new Flutter project.
	
	dependencies:
	  flutter:
	    sdk: flutter
	
	  # The following adds the Cupertino Icons font to your application.
	  # Use with the CupertinoIcons class for iOS style icons.
	  cupertino_icons: ^0.1.0
	  camera:
	
	dev_dependencies:
	  flutter_test:
	    sdk: flutter
	
	
	# For information on the generic Dart part of this file, see the
	# following page: https://www.dartlang.org/tools/pub/pubspec
	
	# The following section is specific to Flutter.
	flutter:
	
	  # The following line ensures that the Material Icons font is
	  # included with your application, so that you can use the icons in
	  # the material Icons class.
	  uses-material-design: true
	
	  # To add assets to your application, add an assets section, like this:
	  # assets:
	  #  - images/a_dot_burr.jpeg
	  #  - images/a_dot_ham.jpeg
	
	  # An image asset can refer to one or more resolution-specific "variants", see
	  # https://flutter.io/assets-and-images/#resolution-aware.
	
	  # For details regarding adding assets from package dependencies, see
	  # https://flutter.io/assets-and-images/#from-packages
	
	  # To add custom fonts to your application, add a fonts section here,
	  # in this "flutter" section. Each entry in this list should have a
	  # "family" key with the font family name, and a "fonts" key with a
	  # list giving the asset and other descriptors for the font. For
	  # example:
	  # fonts:
	  #   - family: Schyler
	  #     fonts:
	  #       - asset: fonts/Schyler-Regular.ttf
	  #       - asset: fonts/Schyler-Italic.ttf
	  #         style: italic
	  #   - family: Trajan Pro
	  #     fonts:
	  #       - asset: fonts/TrajanPro.ttf
	  #       - asset: fonts/TrajanPro_Bold.ttf
	  #         weight: 700
	  #
	  # For details regarding fonts from package dependencies, 
	  # see https://flutter.io/custom-fonts/#from-packages

  ```
  • main.dart
  • app的入口文件
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutterwhatsapp/whatsapp_home.dart';
import 'package:camera/camera.dart';

List<CameraDescription> cameras;

Future<Null> main() async {
  cameras = await availableCameras();
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: "WhatsApp",
      theme: new ThemeData(
        primaryColor: new Color(0xff075E54),
        accentColor: new Color(0xff25D366),
      ),
      debugShowCheckedModeBanner: false,
      home: new WhatsAppHome(cameras),
    );
  }
}
  • whatsapp_home.dart
  • app主页
import 'package:flutter/material.dart';
 import 'package:flutterwhatsapp/pages/call_screen.dart';
 import 'package:flutterwhatsapp/pages/camera_screen.dart';
 import 'package:flutterwhatsapp/pages/chat_screen.dart';
 import 'package:flutterwhatsapp/pages/status_screen.dart';

 class WhatsAppHome extends StatefulWidget {
   var cameras;
   WhatsAppHome(this.cameras);
 
   @override
   _WhatsAppHomeState createState() => new _WhatsAppHomeState();
 }
 
 class _WhatsAppHomeState extends State<WhatsAppHome>
     with SingleTickerProviderStateMixin {
   TabController _tabController;
 
   @override
   void initState() {
     super.initState();
     _tabController = new TabController(vsync: this, initialIndex: 1, length: 4);
   }
 
   @override
   Widget build(BuildContext context) {
     return new Scaffold(
       appBar: new AppBar(
         title: new Text("WhatsApp"),
         elevation: 0.7,
         bottom: new TabBar(
           controller: _tabController,
           indicatorColor: Colors.white,
           tabs: <Widget>[
             new Tab(icon: new Icon(Icons.camera_alt)),
             new Tab(text: "CHATS"),
             new Tab(
               text: "STATUS",
             ),
             new Tab(
               text: "CALLS",
             ),
           ],
         ),
         actions: <Widget>[
           new Icon(Icons.search),
           new Padding(
             padding: const EdgeInsets.symmetric(horizontal: 5.0),
           ),
           new Icon(Icons.more_vert)
         ],
       ),
       body: new TabBarView(
         controller: _tabController,
         children: <Widget>[
           new CameraScreen(widget.cameras),// 相机模块
           new ChatScreen(),//聊天模块
           new StatusScreen(),//状态模块
           new CallsScreen(),//电话模块
         ],
       ),
       floatingActionButton: new FloatingActionButton(
         backgroundColor: Theme.of(context).accentColor,
         child: new Icon(
           Icons.message,
           color: Colors.white,
         ),
         onPressed: () => print("open chats"),
       ),
     );
   }
 }