一,介紹
1.1,Dart
Dart 是一種 易于學習、 易于擴充、并且可以部署到 任何地方 的 應用 程式設計 語言。并且同時借鑒了Java和JavaScript。Dart在靜态文法方面和Java非常相似,如類型定義、函數聲明、泛型等,而在動态特性方面又和JavaScript很像,如函數式特性、異步支援等。
1.2,Flutter
Flutter 是 Google推出并開源的移動應用開發架構,主打跨平台、高保真、高性能。開發者可以通過 Dart語言開發 App,一套代碼同時運作在 iOS 和 Android平台。 Flutter提供了豐富的元件、接口,開發者可以很快地為 Flutter添加 native擴充。同時 Flutter還使用 Native引擎渲染視圖。
二,開發環境配置
2.1,安裝Flutter
第一步:配置鏡像
由于在國内通路Flutter有時可能會受到限制,Flutter官方為中國開發者搭建了臨時鏡像,大家可以将如下環境變量加入到使用者環境變量中:
1 export PUB_HOSTED_URL=https://pub.flutter-io.cn
2 export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
如下圖所示:

第二步:擷取Flutter SDK
去flutter官網下載下傳其最新可用的安裝包,下載下傳位址:
https://flutter.dev/docs/development/tools/sdk/releases,打開後如圖所示:
1、将安裝包zip解壓到你想安裝Flutter SDK的路徑(如:D:flutter;注意,不要将flutter安裝到需要一些高權限的路徑如C:Program Files)。
2、在Flutter安裝目錄的flutter檔案下找到flutter_console.bat,輕按兩下運作并啟動flutter指令行,接下來,你就可以在Flutter指令行運作flutter指令了。
第三步:配置環境變量
如果不配置環境變量,在全局環境中是無法使用flutter指令的,轉到 “控制台>使用者帳戶>使用者帳戶>更改我的環境變量”,在Path下添加D:flutterbin條目,儲存即可。
第四步:運作 flutter doctor指令
在Flutter指令行運作如下指令來檢視是否還需要安裝其它依賴,如果需要,安裝它們:
1 flutter doctor
該指令檢查你的環境并在指令行視窗中顯示報告。Dart SDK已經在打包在Flutter SDK裡了,沒有必要單獨安裝Dart。安裝完成後再運作flutter doctor指令來驗證是否安裝成功。
2.2,windows與mac本配置(模拟器)
windows下sdk與jdk配置:
https://help.aliyun.com/knowledge_detail/40814.htmlmac本下sdk與jdk配置:
https://yq.aliyun.com/articles/2509512.3,編輯器配置
常用編輯器是VS Code,故此這兒主要介紹VS Code的配置,VS Code支援Flutter運作和調試。
安裝flutter插件
啟動 VS Code。
調用 View>Command Palette…。
輸入 ‘install’, 然後選擇 Extensions: Install Extension action。
在搜尋框輸入 flutter ,在搜尋結果清單中選擇 ‘Flutter’, 然後點選 Install。
選擇 ‘OK’ 重新啟動 VS Code。
驗證配置
調用 View>Command Palette…
輸入 ‘doctor’, 然後選擇 ‘Flutter: Run Flutter Doctor’ action。
檢視“OUTPUT”視窗中的輸出是否有問題
建立Flutter應用
啟動 VS Code
輸入 ‘flutter’, 然後選擇 ‘Flutter: New Project’ action
輸入 Project 名稱 (如myapp), 然後按Enter鍵
指定放置項目的位置,然後按藍色的确定按鈕
等待項目建立繼續,并顯示main.dart檔案
VS Code格式化dart代碼的快捷方式是shift+alt+f
三,項目搭建
第一步:建立Flutter應用
1 flutter create yingqi_flutter
第二步:底部tab
Flutter中的路由管理和原生開發類似,無論是Android還是iOS,導航管理都會維護一個路由棧,路由入棧(push)操作對應打開一個新頁面,路由出棧(pop)操作對應頁面關閉操作,而路由管理主要是指如何來管理路由棧。
1 final result =
2 await Navigator.of(context).push(MaterialPageRoute(builder: (context) {
3 return LoginPage();
4 }));
1 Navigator.pop(context, "refresh");
1 class AppHomeState extends State<AppHome> {
2 final appBarTitles = ['首頁', '資訊', '産品', '我的'];
3
4 ...
5
6 int _tabIndex = 0;
7
8 var tabImages;
9 var _body;
10 var pages;
11
12 Image getTabImage(path) {
13 return Image.asset(path, width: 20.0, height: 20.0);
14 }
15
16 @override
17 void initState() {
18 super.initState();
19
20 ...
21
22 });
23 pages = <Widget>[HomePage(), NewsPage(), ProductPage(), MyPage()];
24 if (tabImages == null) {
25 tabImages = [
26 [
27 getTabImage('images/ic_nav_news_normal.png'),
28 getTabImage('images/ic_nav_news_actived.png')
29 ],
30 [
31 getTabImage('images/ic_nav_tweet_normal.png'),
32 getTabImage('images/ic_nav_tweet_actived.png')
33 ],
34 [
35 getTabImage('images/ic_nav_discover_normal.png'),
36 getTabImage('images/ic_nav_discover_actived.png')
37 ],
38 [
39 getTabImage('images/ic_nav_my_normal.png'),
40 getTabImage('images/ic_nav_my_pressed.png')
41 ]
42 ];
43 }
44 }
45
46 TextStyle getTabTextStyle(int curIndex) {
47 if (curIndex == _tabIndex) {
48 return tabTextStyleSelected;
49 }
50 return tabTextStyleNormal;
51 }
52
53 Image getTabIcon(int curIndex) {
54 if (curIndex == _tabIndex) {
55 return tabImages[curIndex][1];
56 }
57 return tabImages[curIndex][0];
58 }
59
60 Text getTabTitle(int curIndex) {
61 return Text(appBarTitles[curIndex], style: getTabTextStyle(curIndex));
62 }
63
64 @override
65 Widget build(BuildContext context) {
66 _body = IndexedStack(
67 children: pages,
68 index: _tabIndex,
69 );
70 return MaterialApp( 74 home: Scaffold( 80 body: _body,
81 bottomNavigationBar: CupertinoTabBar(
82 items: <BottomNavigationBarItem>[
83 BottomNavigationBarItem(
84 icon: getTabIcon(0),
85 title: getTabTitle(0)),
86 BottomNavigationBarItem(
87 icon: getTabIcon(1),
88 title: getTabTitle(1)),
89 BottomNavigationBarItem(
90 icon: getTabIcon(2),
91 title: getTabTitle(2)),
92 BottomNavigationBarItem(
93 icon: getTabIcon(3),
94 title: getTabTitle(3)),
95 ],
96 currentIndex: _tabIndex,
97 onTap: (index) {
98 setState((){
99 _tabIndex = index;
100 });
101 },
102 ),
103 ),
104 );
105 }
106 }
第三步:包管理與資源配置
Flutter項目預設的配置檔案是pubspec.yaml,包與資源配置,均修改此檔案
包配置如下圖所示:
dependencies:應用或包依賴的其它包或插件。
flutter:flutter相關的配置選項。
http: ^0.12.0就是項目中需要使用外部包配置,使用如下指令即可下載下傳:
1 flutter packages get
資源配置如下圖所示:
需要使用什麼資源,以圖檔中的格式在assets下繼續添加即可。
第四步:資料緩存
1,在pubspec.yaml檔案中,添加如下包:
1 shared_preferences: ^0.4.3
2,資料記錄類
1 import 'package:shared_preferences/shared_preferences.dart';
2 import 'dart:async';
3
4 class DataUtils {
5
6 ...
7
8 }
3,使用者登入資訊操作
1 static const String SP_USER_NAME = "name";
2 static const String SP_USER_ID = "userId";
3 static const String SP_IS_LOGIN = "isLogin";
4
5 // 儲存使用者登入資訊,data中包含了token等資訊
6 static saveLoginInfo(Map data) async {
7 if (data != null) {
8 SharedPreferences sp = await SharedPreferences.getInstance();
9 String userId = data['UserId'];
10 await sp.setString(SP_USER_ID, userId);
11 String name = data['Name'];
12 await sp.setString(SP_USER_NAME, name);
13 await sp.setBool(SP_IS_LOGIN, true);
14 }
15 }
16
17 // 清除登入資訊
18 static clearLoginInfo() async {
19 SharedPreferences sp = await SharedPreferences.getInstance();
20 await sp.setString(SP_USER_ID, "");
21 await sp.setString(SP_USER_NAME, "");
22 await sp.setBool(SP_IS_LOGIN, false);
23 }
24
25 // 擷取使用者登入資訊
26 static Future<LoginInfo> getLoginInfo() async {
27 SharedPreferences sp = await SharedPreferences.getInstance();
28 bool isLogin = sp.getBool(SP_IS_LOGIN);
29 if (isLogin == null || !isLogin) {
30 return null;
31 }
32 LoginInfo loginInfo = LoginInfo();
33 loginInfo.userId = sp.getString(SP_USER_ID);
34 loginInfo.name = sp.getString(SP_USER_NAME);
35 return loginInfo;
36 }
如需搭建Flutter之環境配置與項目,可采購阿裡雲伺服器,