一. Flutter官网
英文: https://flutter.io/
中文: https://flutterchina.club/
二. Flutter简介
Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。并且Flutter是一款移动应用程序SDK,一份代码可以同时生成iOS和Android两个高性能、高保真的应用程序。
Flutter目标是使开发人员能够交付在不同平台上都感觉自然流畅的高性能应用程序。我们兼容滚动行为、排版、图标等方面的差异。以及Flutter可以对项目进行热更新修复,以最快的速度进行线上项目Bug的修复.
Flutter目前可以跨平台能力目前可以支持, Linux , Android, iOS, Fuchsia.
对比Cordova框架,Flutter框架不是基于Web技术的框架.
Flutter能达到120 FPS超高性能.
使用Flutter搭建的官方App
gitme下载地址如下:
gitme下载地址
Flutter开发, 为四端不同平台的开发者单独列举了相应的文档信息.
iOS, Android, Web, React Native, 针对移动端开发工程师熟悉程度,列举不同的文档, 进行对比式, 进行讲解, 易于开发人员进行理解.
由于楼主是做iOS开发出身的,所以此处着重针对iOS开发进行对比. Flutter框架的主要编程语言为Dart, 此语言类似JS, 所以有JS基础的童鞋上手会很快.
三. 针对iOS开发者接触Flutter
-
UIView相当于Flutter中的什么?
在iOS中, 构建UI的过程中将使用大量的view对象,或者是以UIView为容器,承载其他的UI控件,最终渲染整个页面绘制UI.
然而在Flutter中, 对比的认为Widget相当于UIView, 但是Widget和iOS中的控件并不完全等价.Widget 和 UIView 还是有些区别的。首先,widgets 拥有不同的生存时间:它们一直存在且保持不变,直到当它们需要被改变。当 widgets 和它们的状态被改变时,Flutter 会构建一颗新的 widgets 树。作为对比,iOS 中的 views 在改变时并不会被重新创建。但是与其说 views 是可变的实例,不如说它们被绘制了一次,并且直到使用 setNeedsDisplay() 之后才会被重新绘制。此外,不像 UIView,由于不可变性,Flutter 的 widgets 非常轻量。这是因为它们本身并不是什么控件,也不会被直接绘制出什么,而只是 UI 的描述。
Flutter 包含了 Material 组件库。这些 widgets 遵循了 Material 设计规范。MD 是一个灵活的设计系统,并且为包括 iOS 在内的所有系统进行了优化。
但是用 Flutter 实现任何的设计语言都非常的灵活和富有表现力。在 iOS 平台,你可以使用 Cupertino widgets 来构建遵循了 Apple’s iOS design language 的界面。 -
如何更新Widgets?
在 iOS 上更新 views,只需要直接改变它们就可以了。在 Flutter 中,widgets 是不可变的,而且不能被直接更新。你需要去操纵 widget 的 state。这也正是有状态的和无状态的 widget 这一概念的来源。一个 StatelessWidget 正如它听起来一样,是一个没有附加状态的 widget。
StatelessWidget 在你构建初始化后不再进行改变的界面时非常有用。然而在数据进行更改的时候,使用StatefulWidget 拥有一个 State 对象来存储它的状态数据,并在 widget 树重建时携带着它,因此状态不会丢失。
例如下方是一个静态的 StatelessWidget:
Text(
'I like Flutter!',
style: TextStyle(fontWeight: FontWeight.bold),
);
类似一个固定的Label并且带有固定内容的Label.
带有事件更新的Widget的如下代码所示
class SampleApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
// Default placeholder text
String textToShow = "I Like Flutter";
void _updateText() {
setState(() {
// update the text
textToShow = "Flutter is Awesome!";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: Center(child: Text(textToShow)),
floatingActionButton: FloatingActionButton(
onPressed: _updateText,
tooltip: 'Update Text',
child: Icon(Icons.update),
),
);
}
}
-
由于Widget是不可以动态进行改变的,所以在创建Widget的时候,传入一个Type值或者Boolean值, 进行创建不同类型的Widget, 来动态的显示不同的视图.然而在Widget中body可以加入不同的padding数据, 类似于XIB | Storyboard中的约束.
在 iOS 中,什么东西都会有一个 .opacity 或是 .alpha 的属性。在 Flutter 中,你需要给 widget 包裹一个 Opacity widget 来做到这一点。
针对绘图, Flutter提供了Canvas绘图的一套API. -
线程和同步
Dart是单线程执行模式,但是它支持Isolate(一种让Dart代码运行在其他线程上的方式) Flutter的Event loop 与 iOS中的main loop 相似 Looper是附加在主线程上的.
Dart 的单线程模型并不意味着你写的代码一定是阻塞操作,从而卡住 UI。相反,使用 Dart 语言提供的异步工具,例如 async / await ,来实现异步操作。
举个例子,你可以使用 async / await 来让 Dart 帮你做一些繁重的工作,编写网络请求代码而不会挂起 UI:
loadData() async {
String dataURL = "https://jsonplaceholder.typicode.com/posts";
http.Response response = await http.get(dataURL);
setState(() {
widgets = json.decode(response.body);
});
}
一旦 await 到网络请求完成,通过调用 setState() 来更新 UI,这会触发 widget 子树的重建,并更新相关数据。
下面的例子展示了异步加载数据,并用 ListView 列表渲染展示出来:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(SampleApp());
}
class SampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
List widgets = [];
@override
void initState() {
super.initState();
loadData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: ListView.builder(
itemCount: widgets.length,
itemBuilder: (BuildContext context, int position) {
return getRow(position);
}));
}
Widget getRow(int i) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Text("Row ${widgets[i]["title"]}")
);
}
loadData() async {
String dataURL = "https://jsonplaceholder.typicode.com/posts";
http.Response response = await http.get(dataURL);
setState(() {
widgets = json.decode(response.body);
});
}
}
网友评论