这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战
本篇文章翻译自官方的总览文章,这篇文章基本上把 Flutter 介绍清楚了,如果想从objective-c和swift总体上知道 Flutter 是咋回事,本篇文章是最好的教程了。
以下是正文
本文旨在从高层级提供opengl三重缓冲开不开一个 Flutter 框架结构的总体概览,介绍一些其设计上的核心原则和概念。
Flutter 是一个跨平台的 U仓鼠饲养八大禁忌I 工具包,目的是一份代码可以运行在不同的操作系统上,比如 Android、IOS等等,同时也可以让应用直接和底层的平台服务交互。我们的目标是:尽量用一份代码,开谷歌地球发者就可以在不用的平台上开发出高性能、高保真的 APP。拥抱差异,更少代码,更高性能。
在开发阶段,Flutter 运行在虚拟机上,虚拟机提供了 hot reload 的功能,可以加载每次Objective-C开发者改谷歌安装器动的差异代码,https和http的区别而不需要全代码的编译。在正式版本上,Flutter 应用是直接长沙市天气编译成了机器码:Intel x64、ARM、JavaScript等等。这里说的开发阶段和正式版本是谷歌地球指 Flutter 产物的模式,Flutter 的产物有三种模式 debug、release、profile。Flutter 的 framework 是开源的,开源的协议是 BSD 协议,并且有活跃繁荣的第三方库社区,陈涉世家翻译及原文这些优秀的第三方库很好的补充了 Flutter 的能力。
本文的http 500总览分为以下httpwatch几个部分:
- 分层模型: Fl仓鼠饲养八大禁忌utter 的组成部分
- 响应式 UI : Flutter UI 开发的核心概念
- Widgets 介绍: Flutter UI 代码构谷歌商店下载建的基础
- 渲染流程: Flutter 是如何将 UI 代码转化为屏幕像素点的
- 平台嵌入 的总览: 让移动端和桌面系统运行 Flutter 应用
- 用其他代码集成objective-c和swift Flutter: 介绍 Flutter 可用的不同的技术信息
- Web 的支持: 总结 Flutter 在浏览器环境中的特点
框架分层
从设计上来看,Flutter 框架是可扩展的、分层的。Flutter 由一系列的单独的依赖包组成,而且这些依赖包依赖底层。上层没有权限访问下层,并且框架层的每个部分都是可插拔的。
对于底层的操作系统来说,Flutter仓鼠寿命 应用被打成的应长沙师范学院用包和其他的 Native 应用是一样。平台特定焯是什么梗的嵌入层提供了一个入口:协调底层操作系统来访问一些底层的服务,比如渲染桌面、可访问性、输入等,管理事件循环。这个嵌入层是被特定的平台语言开发的,Android 系统是 Java 和 C++,iOS 和 macOS 系统是 Objective-C/Objecopengl下载tive-C++,Windows 和 LiOpenGLnux 系统是 C++。正是由于这一层的存在,Flutter 代码可以集成进已经存在的应用,也可以直接使用 Flutter 代码打包整个应用。Flutter 为通用的平台提供了一些嵌入器,其他的嵌入器也是存在的。
Flutter 的核心是 Flutter engine,engine 是 C++ 开发的谷歌空间,并且 Flutter 应用提供最 原始的支持,比如协议、通道等等。当新的一帧httpclient需要被绘制的时候,Flutter engine 就会栅格化代码合成的绘制信息。Engine 也为上层封装了访问底层的 API:图形图像化、文本布局、文件和网络 I/O、访问性支持、插件架构、Dart运行时、Dart编译工具链等等。
Flutter engine 暴漏是通过 dart:ui
这个库来暴漏给上opengl怎么开启一层的,这个库用 Dart 类包装了底层的 C++ 代码。像上面说的 engine 的opengl下载功能,这个库包含了驱动输入、图形化、文本渲染系统等功谷歌地图能。
Typic谷歌浏览器下载ally, developers ihttp 404nteract with Flutter th谷歌商店rough theFlutter framework, w谷歌空间hich provides a modern, reactive framework written in the Dart language. It includes a rich set of platform, layout, and foundational libraries, composed of a ser谷歌ies of layers. Working from the bottom to the谷歌翻译 top, we have: 一般来说,开发者通过 Flutter framework 来和 Flutter 交互,这一层是 Dar仓鼠饲养八大禁忌t 代码,提供了现代的、响应式的 Flutter 框架。这一层包括了和平台、布局、基础相关的库,并且也是分层的,自底向上以次有:
-
必要的基础类以及常用的底层代码块的抽象,比如动画、谷歌地图绘制和手势。
-
处理布局的rehttp代理ndering layer,在这一层,可以构建一棵渲染对象的节点树,你也可以动态的操作这些节点,那么httpwatch布局就会自动响应你长沙师范学院的改变。
-
合成抽象的 widgets layer,谷歌浏览器渲染层的每一个渲染opengl是什么意思对象在 Widget 层http://192.168.1.1登录都会有一个 Widget 对象与之对应。另外,在这一层开发者也可以定义一opengl模式些可以复用的组合类,就是这这一层引入了响应从山神开始的诸天之旅式框架。
-
[Material]和[Cupertino]库, 提供了全套的 Material和 iOS 风格的原始组件。
Flutter 框架是相对来说比较小的,一些开发者用到的高级功能大多opengl是什么意思是以包的形式实现的,比如http 404像 camera
和 webview
这样的平台插件,像 characters
、http
、anima谷歌浏览器下载tions
这样的平台无关的包,平台无关的包可谷歌浏览器以objective-c和swift完全依赖 Dart 和http://www.baidu.com Flutter依赖。这些高级包有一些是谷歌浏览器生态共建的,比如支付、苹果证书、动画等等。
下面就从响应式 UI 编程以此向下opengl是什么意思层展开描述。主要内容有,介绍 Widget 是怎么结合到一起的,Widget 是怎么转化为渲染对谷歌地图象的,介绍 Fl长沙师范学院utter 是怎么集成以及互操作平台代码的,最后简要总结Flutter 的 Web支持。
响应式 UI
总体上来说,Flutter 是一个响应式的非声明式的UI 框长生十万年架,这意http 302味着开发者仅仅需要提供程序状态与程序 UI 的映射,框架会在应用opengl模式状态改变的时候自动完成 UI 的刷新。这种设计的灵感得益于 Facebook 的 React 框架,React 框架对很opengl和directx多传统的设计原则进行了重新思考。
在大多数传统的 UI 框架中,UI 的初始化状态只被描述一次从山神开始的诸天之旅,然后为了响应各种事件会单独的更新。这种方法的一个痛点是,随着应用复杂性的增长,开发者需要时刻注意状态的改变是怎么层叠地贯穿整个 U谷歌三件套I 的。比如,考虑下面的 Uopengl和directxI:
上面有许objective-c和swift多状态可以改变的地方:Color box、色带 Slideropengl-legacy、Radio按钮等等。只要用户和 Uhttps和http的区别I 交互,那么改变必须被响应到每一个地方。更麻烦的是,页面一个很小的改动,比如拖动一下色带,可能会导致一系列opengl模式连锁的反应,进而影响到很多看似不相干的代码。比如色带的拖动,文本框里面也要改变。
一种http协议解决的方案是像 MVC 这样的代码开发架构,通过 controller 将数据的改变推送到 model,然后,model 通过 controller 将新的状态 推送给 viehttp 404w。但是,这样的方式其实也是谷歌浏览器有瑕疵的,因为创建和更新 UI 元素是两个单独的步骤,可能会导致不同步。
沿着其他响应式框架的脚步,Flutter 通过 UI 与底层状态彻底的解耦来解决这个问题。在响应式的 API 开发背景下,开发者仅仅创建 UI 的描述,framework 会在运行时使用我们的描述创建或者更新界面。
在 Flutter 中,我们所说的组件仓鼠寿命是 Widget,并且 Widget 是不可变的,可以形成 Widget 树形结构。这些组件用于opengl是什么意思管理独立的布局对象树,布局树用与管理独立的合成对象树。Widget 树到布局树再到合成树。Flutter的核心就是,确保可以有效的修改树中部分节点:把上层树转化成低层级的树(Widget到布局),并且在这些树上传递改变。
在Flutter谷歌翻译中,小部件(类似于React中的组件)由用于配置对象树的不可变类表示。这些小部件用于管理用于布局的独立对象树,然后用于管理用于合成的独立对象树。Flutter的核心是一系列机制,可以有效地在树的修改部分行走,将对象树转换为较低级的对象树,并在这些树之间传播变化。
开发者需要在 Widget 的 build()
方法中将状态转化为 UI:
UI = f(state)
在 Flutter 设计中,build()
方法执行起来会很快,并且没啥副作用,framework 会在需要调用的时http 500候调用它。
这种响应式的框架需要一些特定的语言从山神开始的诸天之旅特征(对象快速实例化和删除),而 Dart 就很符合干这件事。
Wi谷歌浏览器下载dgets
正如前面所提,Flutter 着重强调 Widget 是合陈涉世家翻译及原文成的一个单元。Flutter 应用的 UI 就是 Widget 构建块,并且每一个 Widget 都是opengles3.1扩展包一份不可变的描述。
Widget 在组合的基础上形成一个体系结构谷歌翻译。每一个 Widget 都嵌套在它的父节点里面,并且从父节点接httpwatch受上下文。这种结构一直延伸到根 Widget,像下面的简单代码:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('My Home Page'),
),
body: Center(
child: Builder(
builder: (BuildContext context) {
return Column(
children: [
const Text('Hello World'),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
print('Click!');
},
child: const Text('A button'),
),
],
);
},
),
),
),
);
}
}
在这个代码中,所有的类都是httpwatch Widget。
用户交互的时候会生成事件,App会更新 UI 来响应事件。更新谷歌地球的方式是告诉 frCSSamework 用另一个 Widget 来替换 Widgethttp代理。framework 就会比较 新的仓鼠寿命和旧的 Widget,并且有效的更新 UI。
Flutter 有其自己的实现机制来控制 UI,而不是按照系统所提供的方式:比如说,这段代码是iOS Sopengl三重缓冲开不开witch control和Android control纯 Dart 的实现。
这种方式有以下几点好处:
-
无限谷歌安装器的可扩展性。比如开发者想要一个 Switch 组件,那么可以用任意的方式来创建,不需要局限于操作系统所提供的
-
避免性能瓶颈。这种方式运行 Flutter 一次就合成整个屏幕信息,而不需要在 Flutter 代码和 平台代码之间来回切换
-
将应用的执行和操作系统的依赖长沙师范学院解耦。Flutter 应用在操作系统的所有版本上运行的效果是一样的,即使操作系统改变了他自己的一些控件实现。
组合先与继承
Widget 通常由许多更小的 、用途更单一的 Widget 组成,组合起从山神开始的诸天之旅来的 Widget 往往可以产生更加有力的效果。
理想的效果,设计上概念仓鼠饲养八大禁忌的数量尽可能少,然而实际的总量表要尽可能长沙市天气大。比如说,在 Widget 层,概念只有一个,那就是 Widget
,表示屏幕http协议绘制、布局、用户交互、状态管理、主题定制、动画、路由导航等等。在动画层,只有两个概念:Animation
和Tween
。在渲染层,只有一个概念 RenderObject
,用于描述布局、绘制、点击、可访问。而这些层级中,每一层都有大量的具体opengl-legacy实现来具化概念,比如有几百个 widhttp 500get 和 render对象,几十个动画和插值类型。
Flutter 有意地将类的继承体系设计的浅而宽,opengl怎么开启目的是最大化组合的数量。每一个小粒度的 可组合的Widget尽量聚焦做好自己的功能。核心的功能是抽象的,即使是像间距、对齐这样的基础功能,也被设计成具体的 Widget,而不是把这些功能添加到基础的 Widget 中。因此谷歌商店,假如我们opengl下载想要居中一个组httpclient件,不是添加陈思思 Align
属性,而是使用 Center
组件包裹。
间距、对齐、横向排列、竖向排列,表格等等都是 Widget,布局类型的 Widget 并没有它自己本身可视的样子。但是opengl三重缓冲开不开呢,它们就是控制其他组件的布局。Flutter 也包括了一些功能性组件,这些功能组件也利用这种组合的方法。
比https和http的区别如,Container
是非常常用的组件,它本身是有负责布局、绘制、定位、尺寸的几个小 Widget 组成,具体来说,Container 由 LimitedBox
、Constr长生十万年ainedBox
、Align
、Padding
、DecoratedBox
和 Transform
组成。Flutter 的一个很明显的特征是,我们可以深入源码,去看去检查源码。因此,我们不需要谷歌空间泛化一个 Container
来实现自定义的效果,我们可以把它和另外一些 Widget 进行组合,或者参考http://192.168.1.1登录 Contai谷歌ner
写一个新的 Widget。
构建 Widget
正如前面提到的,build()
方法CSS返谷歌商店下载回的内容就是页面上显示的内容,返回的元素会形成一颗 Widget 树,这个树以更具体的方式来表示 UI 的一部分。opengl是什么意思比如说,toolbar Widghttp协议et 的 build 方法 构建了横向的布局,包括了 文本、按钮等等。根谷歌空间据需要,framewo焯是什么梗rk 会递归的 build 每一个 Widget 直到 Widget 树可以被更具化的渲染对象完全描述下来。framework 会将渲染对象拼合成一颗渲染树。
Widget 的 build 方法应该谷歌三件套是无副作用的。只要方法被调用了,那么objective-c和swift不管旧的 Whttpwatchidget 树是什么,一颗新的 Widget 树都会被创建。framework 做了大量的工作,来决定哪一个 Widget 的 build 方法需要被执行。具体的过程可以参考Inside Flutter topic。
在每一个渲染帧,Flutte谷歌地图r 仅仅会再谷歌三件套次创建 UI 中需要创建的部分,这一部分就是状态变化的地方,创建的方式是执行谷歌商店 buiHTTPld 方法。所以,build 方法耗时应该非常谷歌商店下载小。一些比较重的计算应objectivec是c语言吗该放在异步中,将计算的结果作为状态的一部分,build 方法只是用数httpclient据。
虽然这种方式相对有点直白,但是这种自动比较的方式很高效,能够保正高性能、高保httpwatch真。而且,build 方法的这种设计可以简化代码,让开发者聚焦在 Widget 的声明上,脱离状态与 UI 复杂的交互。
Widget state
框架里面有两个最主要的 Widget 类:StatefulWidget和StatelessWidget。
许多 Widget 都是无状态的:它们的属性不随着时间改变。这样的 Widget 是 Statehttp 404lessWidget
的子类。
但是呢,如果 Widget 的某个特征需要根opengl是什么意思据用户交互或者其他因素发生改变,那么这种 Widget 是 StatefulWidget
。比如说,如果一个 Widget 有一个计数器,当用户点击按钮的时候,计数器需要变化,那么计数器就是 Widget 的 State。当值改变的时候,Widget 需要被陈思思重新构建来更新部分 UI(显示数字的那部分)。这样的 Widget 就是 St长沙师范学院atefulWidget
,因为 Widget 本身谷歌地图是不可变的,opengl版本过低怎么办所以把状态存储在 可变objective-c和swift的 State
子类中。Statef陈涉世家翻译及原文ulWidget
没有 build 方法,相反,它的 UI 构建放到了 S辰时是几点到几点tate
对象中。仓鼠寿命
只要想要改变 State
对象的状态,那么https和http的区别就调用 setState()
方法来告诉 framework : 你应该调用我的 buObjective-Cild 方法来更新 UI 来。
虽然 StatefulWidget
既有辰时是几点到几点 State
对象又有Widget
对象,但是其他 Widget 可以像使用 Sta长沙师范学院telessWidget
一样使用 StatefulWidget
,担心状态丢失等问题。父节点在需要的时候可以随时创建子组件,不需httpwatch要保留前一个 state 对象,framework 做了查找和重用状态对象的所有工作。
状态管理
因此,如果保持状态的 Widget 非常的多,那么状态是怎么管理的呢?是怎么更好的在应用内传递呢?
像其他的类一样,开发者可以在 Widget 构造方法中初始化它的数据,build(焯是什么梗)
方法可以确保其用的数据已经初始化了:
@override
Widget build(BuildContext context) {
return ContentWidget(importantState);
}
随着节点树越来越深,状态的向上向下CSS查找就变的十分糟糕了。因此,另一种类型的 Widget —— InheritedWidget
就应运而生了。这种类型的 Widget 提供了一谷歌商店下载个很容易的方式来获取祖先节点的数据。可以使用 InheritedWidget
来创建一个 StatefulWidget
祖先节点,就像下面一样:
Whenever one of theExamWidget
orExamWidget
objects needs data fromStudentState
, it can now access it with a command such as:
只要 ExamWidget
或者 ExamWidget
需要 StudentState
的数据,那么可以使用下面的方式:
final studentState = StudentState.of(context);
of(contex谷歌空间t)
从 context 开始向上查找,找到最近的指定类型的祖先节点。这里的类型是StudentStahttpclientte
。InheritedWidget
也提供了一个 updateShouldNotify()
方法,这个方法决定了当状态改变的时候,是否来触从山神开始的诸天之旅发使用数据opengl是什么意思的子opengl版本过低怎么办节点的更新重建。
Flutter 本身就广泛的使用 InheritedWidget
来共享状态,比如我们熟知的主题。Mate仓鼠寿命rialApp
的 build()
方法中插入了一个 theme 节点,并为 theme 填充了数据,这样 比theme 节点更深的节点就可以通过 .of()
来找到 theme 节点,并使用数据。比如:
Container(
color: Theme.of(context).secondaryHeaderColor,
child: Text(
'Text with a background color',
style: Theme.of(context).textTheme.headline6,
),
);
Navigator 也用了这种方式,我们经常使用 Navigator 的 of 方法来 push 或者 pop 路由。MediaQuery 也用这种方式让开谷歌地球发者可以很快捷的获取屏幕谷歌商店下载相关信息,尺寸、方向、密度、模式等等。
随着应用的增长,更加先进高级的状态管理方案更加符合生产环境的开发,可以减少 StatefulWidget
的使用。许多 Flutter 应用使用 provider 这样的开源库。前面提到 Flutter 的分层结构可以无限扩展,flutter_h仓鼠饲养八大禁忌ooks 这个第三方库提供了另外一种将状态转为 UI 的方式。
渲染与布局
这一节主要描述渲染管线,渲染管线包括了几个重要的步骤,将 Widget 真正的转化为http://192.168.1.1登录实际的绘制像素。
Flutter 渲染模型
你可能会好奇:既然 Flutter 是一个跨平台的框架,它是怎么做到和单平台框架相当的性能效果呢?
我们先想一下传统的 Android app 是怎么运行的。当需要绘制的时候,开opengl怎么开启发者需要首先调用 Android 框架的 Java 代码。Android 系统提供的http 302组件负责在 Canvas 对象中http 404绘制,Android 使用谷歌空间 Skia
进行渲谷歌商店下载染。Skia
是 C/C++ 开发的图形库,会调用 CPU 或者 GPU 完成设备屏幕的绘制。
跨平台框架通常的做法是:在原生的 Android and iOS UIhttp 500 层上http://www.baidu.com创建一个抽象层,来尝试磨平每个平台的差异性。应用http 500的代码一般是opengl-legacy解释语言——JavaScript谷歌浏览器,必须和Java/Objectopengl版本过低怎么办ive-C反复的opengl怎么开启交互来显示 UI。这些都增加了高额的负担,尤其是 UI 层和谷歌逻辑层有大量交互的时候。
Fl长沙师范学院utter 另辟蹊径,Flutter 最小化了这些抽象,避开系统提供的 UI,它自己有丰富的 Widget 库。绘制 Flutter 的 Dart 代仓鼠饲养八大禁忌码最终转为 native 代码,而这些 native 代码会使用 Skia 进行渲染。 Flutter 把 Skiopengl是什么意思a 作为 引擎的一部分,这样开发者可以始终让应用保持焯是什么梗到最新版本,而 Android 设备不需要更新。IOS等http://www.baidu.com其他的设备也是相同的道理。
从用户输入到 GPU
Flutter 渲染管线的总长沙市天气原则是:简单就是快,Flutter 有一个简单明了的数据传输管道,沿着这个通道用户的输入流到了系统。正如下面所示:
下面我们来看更多的细节。
Build: 从 Widget 到 Element
Consider this code fragment that长沙市天气 demonstrates a widget hierarchy: 思考一下下面的 Widget 体系代码片段:谷歌
Container(
color: Colors.blue,
child: Row(
children: [
Image.network('https://www.example.com/1.png'),
const Text('A'),
],
),
);
当 Flutter 需要渲染这个片段的时候,会调用 build 方法,返回了反应当前程序状态的 Widget 树,然后去渲染 UI。在这个过程中,build()
方法可能会构造新的 Widget。比如,前面的代码中,
Container
有color
和child
属性。但是在 Container
的源码中,如果 color
不是谷歌商店null,那么会插入一个代表颜色的 ColoredBox
组件:
if (color != null)
current = ColoredBox(color: color!, child: current);
同样地,ImagHTTPe
和Text
组件也插入了 RawImage
和Rich仓鼠寿命Text
组件在 build 过程长生十万年中。所以最终的 Widget 树可能会比代码更深,比如:
这就解释了为啥我们在 Flutter inspecthttp://192.168.1.1登录or 看到的节点要谷歌商店下载远远深于我们的原谷歌地球始opengl-legacy代码。
在 bu谷歌地球ild 阶段,Flutt长生十万年er 会将 widget 树 转为 element 树,每一个 Element 都对应一个 Widget。每一个 Elem辰时是几点到几点ent 表示一个指定位置的特定 Widget 实例。有两个不同类型的 Element:
-
ComponentElement
, 承载其他 Element 的 Elementopengl下载 -
RenderObjectElement
, 参与布局和绘制阶段的 Element
RenderObjectElementopengl和directx
是它的 Widget 和 背后的 RenderObject陈涉世家翻译及原文
的中介,这个后面再说。
Widget 的 Element 可以通过 Buhttp 500ildContext
来引用到,同时 BuildContext
也表示树的位置信息。比如 Theme.of(context)
的参数就是 BuildContext
,并且 Bui谷歌空间ldContext
是opengl版本过低怎么办 build 方法的参数。
因为 Widget 是不变的,所以 Widget 树的任意改变都会导致一组新的 Widget 要被创建,即使是像 Text('A')
到Text('B')
这样的变化。但是,Widget 的重新构建,并opengles3.1扩展包不意味着背后的 Element、RenderObject 也要重新构建。Element 树是持久化的在帧与帧之间,Flutter 的高性能很大一原因就是这个持久化的设计。Flutter 会缓存 Element等背后的对象,所以完全舍弃旧的Widget 也没啥问题。通过只遍历已经修改的 Widget,Flutter可以仅仅重建需要重建的 Element 树。
布局和渲染
仅仅绘制一http 302个 Widget 的应用几乎是不存在的。因此,框架需要高效的布局 Widget 层次树,并且在渲染在屏幕上之前,也要高效的计算 Element 的尺寸,标定 Element 的位置。
渲染对象仓鼠饲养八大禁忌的基类是 RenderObject
,这谷歌商店下载个类定义了布局和绘制的通用抽象模型,像多维、极坐标这样的需要自定义渲染模陈思思型。每个 RenderObject
知道它的父辰时是几点到几点节点是谁,但是子节点的信息知道的谷歌地球很少,仅仅知道怎么opengl是什么意思去 visit 子节点和子节点布局http代理约束长沙师范学院。但是对于抽象来说这就够了,RenderObject
可以处理各opengl是什么意思种用例。
在 build 阶段,Flutter 会创建或者更新 element 树上每一个 RenderObjectElemen谷歌浏览器下载t
背后的 RenderObject
对象。
RenderObject
是原始的抽象类:RenderParagraph
渲染文本,RenderImage
渲染图像,RenderTransform
会谷歌三件套在子节点绘制之前应用https和http的区别位置等信息。
大多数 Flutter Widget 背后的渲染谷歌浏览器对象是 RenderBox
的子类,RenderBox
将模型定义为盒子模型——固定大小的二维笛卡尔坐标。RenderBox
提供http 404基本的 盒子约束,每一个 Widghttp://192.168.1.1登录et 都放在由最大最小宽度、最大最小高度限制的盒子内。
为了执行布局过程,Flutter 向下传递约束。向上传递尺寸。父节点设置位置。
布局的遍历完成之后,每个对象都有了符合父节点约束的尺寸,就会调用 paint()
方法进行绘制。
盒子约束模型非常棒,布局的过程时间复杂度仅是*O(n)*的:
-
父节点可谷歌地图以将最大值和最小值设置为相同的,这样子节点的大小就是固定的了。比如说,最根部的节点就强制其子节点为屏幕大小。(子节点可以选择如何使用这一部分空间,比如,子节点可以在空间仓鼠饲养八大禁忌内居中摆放)
-
父节点可以让设置子节点的宽度,但是让高度灵活可变。或者设置高度谷歌浏览器下载,让宽度灵活可变。比如文本组件,文本组件的宽度是灵活可变的,高度是固定的。
除了上述描述:子节点要根据可用空间的多少来展示自己的显示也是可行的。使用 LayoutBuilder
可以达到这样的效果,子节点检查父节点传进来的约束,然后仓鼠寿命使用约束的信息来谷歌翻译展示自己的内容,比如:
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < 600) {
return const OneColumnLayout();
} else {
return const TwoColumnLayout();
}
},
);
}
布局和约束更加详细的opengl三重缓冲开不开内容可以看这一篇文章深入理解Flutter布局约束谷歌三件套
所有RenderObject
的根节点是 Rendehttp协议rView
,它就代表一颗渲染树。当平台决定绘制新的一帧时,就会调用 RenderView
的 compObjective-CositeFram谷歌三件套e()
方法,方法内部创建了 SceneBuild仓鼠寿命er
去更新 scene
。当 scene
准备完成之后,RenderView
对象会将合成的 scene
传递给
dart:ui
内的 Window.render()
方法,然后 GPU 就会渲染合成信息。
合成和光栅化陈涉世家翻译及原文阶段的更多细节可以参考 Flutter 渲染管线
Platform emb谷歌商店下载edding
正如我谷歌们所示,Flutter 不像 React Native,把自己的组件转为 OS 的组长沙师范学院件,让 OS 去渲染https和http的区别,它 是自己完成 build、布局、合成、绘制。获取纹理和 App 生opengl-legacy命周期的机制也会因为平台的原因有所不同,比如 Android 的纹理和 IOS 的纹理在实现上就有所不同。Flutter 引擎仓鼠寿命是平台无关的,表现出来是 应谷歌地图用二进制接口,提供了一种仓鼠寿命平台嵌入器,可以安装和使用 Flutter。
平台嵌入器是一个原生系统的应用程序,承载着 Flutter 的所有的内容,并且充http://192.168.1.1登录当了原生操作系统与 Flutter 之间的粘合剂。当我们打开 Flutter 应用的时候,嵌入器提供了一个入口:初始化 Flutte谷歌商店r 引擎,获得 UI 线程和 光栅,创建 Fopengl渲染gpu怎么设置lutter 纹理。嵌入器也负责:应用的生命周期、手势输谷歌浏览器下载入、窗口尺寸、线程管理和平台消息。Flutter 包含了 Android、iOS、Windows、macOS、Linux。开发者也可以自定义平台嵌入器,有两个比较不错的案例 案例1 和 案例2——Raspberry Pi。
每一个平台尤其本身的API和约束。一些简明的平台原则如下:
-
在 iOS 和 macOS,Flutter 是作为
UIViewController
或者opengl怎么开启NSViewCont谷歌浏览器下载roller
而被加载进嵌入器的。平台嵌入器长生十万年创建了FlutterEngine
,而引擎可以当作 Dartopengl-legacy VM 和 Flutter 运行时的宿主。objective-c和swiftFlutterViewController
和http代理FlutterEngine长生十万年
相绑定,将 UIKit 或者 Cocoa 输入事件传递给 Flu谷歌地图tter,并且使用 Metal谷歌空间 或者 OpenGL 来渲染帧。 -
在 Android 上,Flutter 默认加载到
Activity
中,视图就是Flutt焯是什么梗erView
,FlutterView
可以渲染 Flutter 的内容(ui 或者 纹理,取决于合成信息和 z 轴顺序), -
在 Windows 上,Flutter 被装载在传统的 Win32 应用中。Flutter 内容使用 ANGLE 渲染,
这个库可以将 OpenGL A谷歌翻译PI 转为辰时是几点到几点与之等价的 DirectX 11。目前正在做的事情是,提供一个使用 UWP 应用模型的谷歌地球 Windows 嵌入器,以及使用更加高效直接的方式将 DirectX 12 到 GPU,替换现有的 ANGL陈涉世家翻译及原文E。
集成其他CSS代码
Flutter 提供了一些互操作的机制,访问 Kotlin 或者 Swift 编写的代码,调用 基于 C 的本地 API,在 Flutter 中嵌入原生组件,在既有应用中嵌入 Fluthttp协议ter。
Platform channelshttpclient
对于移长生十万年动端和桌面 App,通过 platform channel 机制,Flutter 可以让开发者调用自定义代码。platform channel 是 Dart 代码和 App 宿主平台代码通信的机制。通过创建一个通用CSS的 channel (指定名字和编解码器),开发者能够在 Dart 和平台之间发送和接受消息。数据会被序列化,比如 Dart 的 Map 就是 Kotlin 中的 HashMap
,Swift 的 Dictionary
。
下面是简单的事件处理器的代码,Android 是 Kotlin,iOS 是 Swift,Da谷歌地球rt 调用原生的方法,并获取数据:
// Dart side
const channel = MethodChannel('foo');
final String greeting = await channel.invokeMethod('bar', 'world');
print(greeting);
// Android (Kotlin)
val channel = MethodChannel(flutterView, "foo")
channel.setMethodCallHandler { call, result ->
when (call.method) {
"bar" -> result.success("Hello, ${call.arguments}")
else -> result.notImplemented()
}
}
// iOS (Swift)
let channel = FlutterMethodChannel(name: "foo", binaryMessenger: flutterView)
channel.setMethodCallHandler {
(call: FlutterMethodCall, result: FlutterResult) -> Void in
switch (call.method) {
case "bar": result("Hello, (call.arguments as! String)")
default: result(FlutterMethodNotImplemented)
}
}
像这样的 channel 代码,可以在 flutter/plugins 仓库中找到,里面也有谷歌地球响应的 macOS 的实现。一些通用的场景大概有几千个可用插件,从广告到相机、蓝牙这样的硬件设备。
外部方法接口
对于 C基础的 API(包含 Rust、Go 生产的代码),Dart 也提供了直接的调用机制,可以使用 dart:ffi
依赖库来绑定 native 代码。Foreign function interface (FFI) 模型 没长沙师范学院有数据数据序列化过程,所以它比上面的 cha仓鼠寿命nnel 更快。Dart 运行时提供了在堆内存上辰时是几点到几点分配内存的能力,堆上的内存是仓鼠饲养八大禁忌 Dart 对象内存,并且可以调用静态谷歌商店下载和动态的链接库。FFI 可用在除 web 之外的所有平台上,因为 js package 提供了相同的能力。
要使用 FFI长沙师范学院 的话,可以创建一个 typedef
为每一个 Dart 的非管理的方法签名,并且opengl三重缓冲开不开指定 Dart VM 做了映射。下面是一个案例,调用 Win32MessageBox()
的 API:
typedef MessageBoxNative = Int32 Function(
IntPtr hWnd,
Pointer<Utf16> lpText,
Pointer<Utf16> lpCaption,
Int32 uType,
);
typedef MessageBoxDart = int Function(
int hWnd,
Pointer<Utf16> lpText,
Pointer<Utf16> lpCaption,
int uType,
);
void exampleFfi() {
final user32 = DynamicLibrary.open('user32.dll');
final messageBox =
user32.lookupFunction<MessageBoxNative, MessageBoxDart>('MessageBoxW');
final result = messageBox(
0, // No owner window
'Test message'.toNativeUtf16(), // Message
'Window caption'.toNativeUtf16(), // Window title
0, // OK button only
);
}
在 Flutter 应用中渲染原生组件
因为 Flutter 内容是被绘制在纹理上的,并且 组件树完全是内部的。像 Android view 存在在 Flutter 内部模型中,或者在 Flutter 组件交错渲染,这些情况我们咩有看到。如果不能支持的话,是有问题的,比如一些原生组件不能用的OpenGL话,就很麻烦。比如 WebView。
Flut辰时是几点到几点ter 解决这种问题是通过平台视图 Widget 的方式(AndroidView
和UiKitView
)。这些组件可以嵌入平台原生组件。Platform Widget 可以和httpwatch其他的 Flutter 内容一起CSS集成,并且充当着与底层操作系长生十万年统的中介。比如,在Android上,AndroidView
有三个主要的功http协议能:
-
复制原生视图的图形纹理,并把纹理作为 Flutter 合成渲染的一部分,所以在每一帧的opengl渲染gpu怎么设置时候都会进行这样的合成绘制。
-
响应手势,并且把手势转为等价于 Native 的输入。opengl怎么开启
-
创建一个可访问性树的模拟,并且在原生和 Flutter 层之间传递和响应命令
显而易见的,每帧的合成都是相当耗时的,像音长沙师范学院视频也非常耗内存。所以,这种方法一般会在复杂交互的时候采用,比如 Google Maps 这样的,Flutter 不太具有生产实践意义的。
通常,一个 Flutter 应用也是objectivec是c语言吗在 build长沙师范学院()
方法中实例化这些组件,比谷歌商店如,google_maps_flutter创建了地图插谷歌安装器件:
if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView(
viewType: 'plugins.flutter.io/google_maps',
onPlatformViewCreated: onPlatformViewCreated,
gestureRecognizers: gestureRecognizers,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
);
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
return UiKitView(
viewType: 'plugins.flutter.io/google_maps',
onPlatformViewCreated: onPlatformViewCreated,
gestureRecognizers: gestureRecognizers,
creationParams: creationParams,
creationParamsCodec: const StandardMessageCodec(),
);
}
return Text(
'$defaultTargetPlatform is not yet supported by the maps plugin');
AndroidView
或者UiKitView
使用的我们前面提到的谷歌地球 platform chCSSannel 机制来和 原生代码交互。
目前,Plopengl渲染gpu怎么设置atform Widget 在桌面平台上是objectivec是c语言吗不可用的,但是这不是架构上的限制,后面可能会添加。
宿主 App 接入 Flutter
和前面Flutter 嵌入 nati陈涉世家翻译及原文ve 相反,这一节介绍 既有应用中嵌入 Flutter。前面我们提到谷歌地球了 Flutter 是被 And陈涉世家翻译及原文roid 的 Activhttp 302ity,i焯是什么梗OS 的 UIViewController
承载的,Flutter 的内容可以用相同的方式被嵌入。
Flutter module 模opengles3.1扩展包版很容易被嵌入,开发者可以使用 Gradle 或者 Xco辰时是几点到几点de 进行源码依赖,也可以产物依赖。产物依赖的方式的好处就是项目组的成员不需要每个人都安装 Flutter 环境。
Flutter 引擎需要一点的时间初始化,因为需要加载 Flutter 依赖库,初始化 Dart 运行时,创建和运行 Dart 线程,绑定渲染 suobjective-c和swiftrfa谷歌商店ce 到 UI。为了最小化上面提到的时间,减少呈现 Flutter UI 的延迟,最好的处理方式是在程序初opengl怎么开启始化的时候,初始化 Fl长沙师范学院utter 引擎,至少在第一个 第一个Flutter屏幕之前,这样用户不就会在显示 FHTTPlutter 第一个页面的时候,出现短暂的白屏或者黑屏。
关于接入的更多信息,可以在 Load sequence, performance and memoryopengl怎么开启 topic找到。
Flutter web support
一些通用的框架概念适用于 Flutter 支持的所有平台,但是opengl渲染gpu怎么设置呢,Flutter’s web 有一些值得讨论的独特的点。
自JavaScript语言存在以来,Dart就一直在编译JavaScript,并为开发和生产目的优化了工具链。许多重要的应用程序从Dart编译到JavaScript,并在今天的生产中运行,包括谷歌Ads的广告商工具。因为Flutter框架是用Dart编写的,所以将它编译成JavaScript相对简单。
从 Dart 语言面世以来,Dart 就一直在支opengl版本过低怎么办持编译成 JavaScript,并且持续的为开发Objective-C和生产优化工具链。许谷歌商店下载多重要的程opengl-legacy序从 Dart 编译成 JavaScript,并在今天一直在运行,比如 advertiser tooling for Googl谷歌地球e Ads。因为 Flutter 框架是 Dart 开发的,把 Dart 编译成 Jav谷歌翻译aScript 相对来说是简单直接的。
However, the Flutter engine, written in C++, is designed to interface with the uopengles3.1扩展包nderlying operating system rather than a web browser. A different approach is therefObjective-Core required.opengl是什么意思 On the web, Flutter provides a reimplementat谷歌商店下载io谷歌空间n of the engin焯是什么梗e on top of standard browser APIs. We currently have twoobjectivec是c语言吗 options for rendering Flutter content on the web: Hhttp 302TML and WebGL. In HTML mode, Flutter uses HThttp协议ML, CSS, Canvas, and SVG. To render toobjectivec是c语言吗 WebGLopengl版本过低怎么办, Flutter uses a version of Skia compiled t长沙市天气o WebAssembly calledCanvhttps和http的区别asKit.谷歌三件套 While HTML mode offers the best code size characteristics, CanvasKit provides the fasthttp 302est path to the browser’s graphics stack, and offers somewhat higher graphical谷歌地图 fidelity with the native mobile targets5. 然而,C++ 开发的 Flutter 引擎是操作系统底层的接口,而不是浏览器。因此,需要采取一个不同的方法。在 web 上,Flutter 在标准浏览器 API 之上 提供了重新实现。目前,在 Webhttp代理 上渲染 Flutter 有两个方案:HTML 和 Weobjective-c和swiftbGL。HTML 模式下,Flutter 使用 HTML、 CSS、 Canhttp 302vas 和 SVG。CSSWebGL 模式下,Flutter 使用 CanvasKit 编译成httpwatch WebAssembly。 HTML 模式的包体积会很小,而 CanvasKit 的渲染会更快、渲染效果更佳opengl-legacy高保真。
Web 版本的架构图是下面的:
和其他 Flutter 平台相比,最显著的区别是:不需要提供一个 Dart 的运行时。相反,Flutter 的framework 被编译成了 JavaScript。在 Dart 的众多模式中,比如 JIT、opengl渲染gpu怎么设置AOT、native、web,语言语义上的差别很小,开发者也不会在开发的谷歌空间过程中体验到差异。
在开发期间,Flutter web 使用 dartdevc
,它支持增量编译,这就可以 hot restart 了。相反,如果想要创建opengl是什么意思一个线上正式版本的 web,就会使用 dart2js
编译器,这是一款高性能的 JavaScript 编译器,会将 Flutter 核心和框架长沙市天气与应用程序打包为可部署到谷歌浏览器下载任何 web 服务器的小型源文件。deferred imports 可以将代码封装为一个文件,或者分割为多个文件。
展望
如果想要更加深入了解 Flutterhttpwatch 内部的机制,那么可以看 InsObjective-Cide Flhttp://192.168.1.1登录utter 文章。