Flutter系列一:Flutter快速入門

NO IMAGE

Flutter快速入門

前言

Flutter安裝及Hello World請看官方文檔,本教程不做介紹

Flutter與其它移動開發框架

原生開發框架工作原理圖

Flutter系列一:Flutter快速入門

基於Webview框架的工作原理圖

Flutter系列一:Flutter快速入門

RN工作原理圖(嚴重依賴OEM組件)

Flutter系列一:Flutter快速入門

Flutter工作原理圖

Flutter系列一:Flutter快速入門

Flutter與其它方案對比

  • Flutter與JS解決方案一樣,使用AOT(提前編譯),而不是JIT(實時編譯)
  • 與其它方案相比,Flutter性能要好得多
  • Flutter消除了Bridge,且不依賴於OEM平臺
  • Flutter允許自定義組件使用屏幕上的所有像素,即使用Flutter開發的應用程序在安卓和iOS的每個版本上都顯示相同的內容
  • Flutter使用Widgets Rendering來處理畫布(canvas)和事件(events),使用Platform Channels來使用服務(位置、藍牙等)
  • Flutter Hot Reload使用了Dart的JIT編譯特性

Flutter的四種調試方式

Dart analyzer

可以創建analysis_options.yaml文件,指定配置,有助於編寫更好的Flutter代碼

Dart observatory

可以通過添加斷點或者debugger()語句,中斷應用執行進行調試,更多說明

Visual debugging

  • 啟用debugPaintSize選項,在入口文件處,指明debugPaintSizeEnabledtrue,代碼及效果如下:
void main() {
debugPaintSizeEnabled=true;
runApp(MyApp());
}

Flutter系列一:Flutter快速入門

  • 類似的還有啟用debugShowMaterialGrid,進行MaterialApp的網格調試
  • 啟用showPerformanceOverlay,將展示性能圖,性能圖分為上下兩部分。上部為GPU線程花費的時間,下部為CPU線程花費的時間

Flutter widget inspector

Flutter系列一:Flutter快速入門

類似於Web調試的瀏覽器選擇工具,選擇後效果如下

Flutter系列一:Flutter快速入門

Flutter系列一:Flutter快速入門

Flutter的Widgets

說明

Flutter UI裡一切皆Widgets,寫過React及Styled-Components應該很容易理解,不過Flutter的部分樣式也是由Widget組成,例如:Padding、Center等

常用Widgets列表

Container

使用示例

Center(
child: Container(
height: 200.0,
width: 200.0,
child: Image.network("https://flutter.io/images/flutter-mark-square-100.png"),
),
),

Container可以用於條件表達式展示一個空組件,如

function getIcon(bool condition) {
if (condition == true) return Icon(Icons.edit);
else return Container();
}

Image

Text

Icon

RaisedButton

Scaffold:Scaffold用於展示drawers, snackbars, bottomsheets, floating-action buttons等,使用示例

RaisedButton(
onPressed: () {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text("HELLO!"),
));
},
child: Text("BUTTON"),
color: Colors.blue,
),

Appbar

PlaceHolder

Row

Column

ListView

GestureDetector:為非按鈕組件添加交互性

Stateless widget & Stateful widget

Stateless widget:無狀態的小組件,示例

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}

Stateful widget:有狀態的小組件,示例(通過setState更改state)

class _MyHomePageState extends State<MyHomePage> {
bool value = false;
@override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: value ? Colors.black : Colors.white,
appBar: new AppBar(
title: new Text(widget.title),
),
body: Center(
child: Switch(
value: value,
onChanged: (v) {
setState(() {
value = v;
});
}),
),
);
}
}

Flutter路由

通過Navigator.push()打開新頁面,通過Navigator.pop()返回上一頁,示例

onPressed() {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()), // SecondScreen為要跳轉到的頁面
);
}

注:要達到全屏模態框的效果可以將MaterialPageRoutefullscreenDialog屬性設置為true

Flutter中的約束

約束給出高度與寬度的最小值與最大值
RenderBoxes有三種不同的渲染機制

  1. 試圖以當期容器的最大寬高渲染,如:ListViewCenter
  2. 試圖以其子組件寬高作為自身寬高渲染
  3. 試圖以特定寬度渲染,如:ImageText

特殊的:當未向Container構造函數傳入寬高值時,它將傾向於最大渲染,但如果指明瞭寬高值,則使用特定大小。
特定的約束是無界(限)約束,這種情況下最大寬高將被設置為double.INFINITY

Flutter中的網絡請求

示例

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<Post> fetchPost() async {
final response =
await http.get('http://localhost:3000/Movies/1');
if (response.statusCode == 200) {
return Post.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load post');
}
}
class Post {
final int id;
final String movieName;
final int year;
final String category;
Post({this.id, this.movieName, this.year, this.category});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
id: json['id'],
movieName: json['movieName'],
year: json['year'],
category: json['category'],
);
}
}
void main() => runApp(MyApp(post: fetchPost()));
class MyApp extends StatelessWidget {
final Future<Post> post;
MyApp({Key key, this.post}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'JSON Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('JSON Fetch Data Example'),
),
body: Center(
child: FutureBuilder<Post>(
future: post,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.movieName);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
),
),
);
}
}

GET/POST的通用化原生封裝

import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
class Api {
static bool useHttps = false;
static String prefix = "127.0.0.1:7001";
static void init({String prefix, bool useHttps}) {
Api.useHttps = useHttps;
Api.prefix = prefix;
}
static Future<dynamic> get({
String url,
Map<String, dynamic> param = null,
bool useDecode = true,
}) async {
url = (Api.useHttps ? 'https' : 'http') + '://' + prefix + url;
if (param != null) {
List<String> kv = [];
for (String key in param.keys) {
kv.add(key + '=' + param[key].toString());
}
url += '?' + kv.join('&');
}
print(url);
var client = new http.Client();
var resp = await client.get(url);
if (resp.statusCode != 200) {
return null;
}
if (useDecode) {
var json = new JsonDecoder();
return json.convert(resp.body);
}
return null;
}
static Future<dynamic> post({
String url,
Map<String, dynamic> param = null,
bool useDecode = true,
}) async {
url = (Api.useHttps ? 'https' : 'http') + '://' + prefix + url;
var client = new http.Client();
var resp = await client.post(url, body: param);
if (resp.statusCode != 200) {
return null;
}
if (useDecode) {
var json = new JsonDecoder();
return json.convert(resp.body);
}
return null;
}
}

其它

IDE技巧編寫Flutter效率技巧

Android Studio

  • quickfix(快速修復): Alt + Enter

VS Code

  • quickfix(快速修復): Ctrl + .

Flutter包管理

Flutter Pub

Flutter打開webview

使用flutter官方的url_launcher

Flutter 常用命令

$ flutter packages get # 在項目內部執行,安裝pubspec.yaml指明的依賴
$ flutter channel # 查看渠道列表,及當前在用的渠道
$ flutter channel dev # 切換渠道為dev
$ flutter doctor # 執行flutter環境檢查
$ flutter upgrade # 升級
$ flutter run -d [device ID] # 通過該設備啟動應用

相關文章

前端架構101(二):MVC初探

微前端說明書

深入理解Webpack打包分塊(上)

WebAssembly系列一:WebAssembly介紹