前端的flutter之路(二):項目前期準備

最近時間比較多,就把項目中可能用到的知識用 flutter 大概寫了一遍,因此就分享出來加強下印象。javascript

1. 路由庫:fluro

安裝

官方文檔直接使用版本號的這個部分說錯了,版本號不須要帶引號的,因此正確的方式是在 pubspec.yaml文件中的dependencies的下方加入html

fluro: ^1.5.1
複製代碼

以後編輯器便可根據 flutter 命令自行安裝依賴,或者在項目根目錄運行 flutter pub get,具體流程見 flutter 官網前端

使用

官方文檔說的比較簡略,我看了 flutter go 的代碼之後,總結了這個路由庫的使用方式以下:java

  1. 定義一個類,實現一個方法 對傳入的 Router 實例進行擴展。代碼在這裏
  2. 確保執行代碼的 一開始 進行調用上述的類方法進行路由的初始化,好比 runApp 方法運行以前或者在 根類 MyApp 的構造函數 中,我選擇了後者。router 實例最好是全局變量,這樣在其餘文件中也能訪問代碼在這裏
  3. MaterialApponGenerateRoute 改寫爲如下代碼。在這裏用到了 router,因此必定要在第 2 步中確保路由已經被正確初始化。
onGenerateRoute: (settings) {
  return Application.router.generator(settings);
}
複製代碼
  1. 在頁面中進行跳轉的時候,可使用該庫所提供的方法,router.navigateTo(context, "/users/1234", transition: TransitionType.fadeIn);,也可使用 flutter 提供的路由跳轉方式,Navigator.of(context).pushNamed("/users/1234", arguments: {"from": "ui"})

須要修改頁面轉場動畫使用前者,須要攜帶額外的參數建議使用後者。由於轉場動畫能夠在第 2 步中進行設置,而且前者只提供了動態參數的傳遞,若是須要傳遞 Map數據還得編碼解碼,因此我更人更推薦後者。ios

2. webviewk 庫: webview_flutter

安裝

webview_flutter: ^0.3.16
複製代碼

使用

代碼在這裏git

  1. 在目錄 ios/Runner/Info.plistdict內添加 <key>io.flutter.embedded_views_preview</key> <string>YES</string>
  2. 在文件內引入包以後就能夠直接使用 WebView了,使用方式相對於插件的方式要簡單的多,在定義組件時能夠提供方法供 js 使用,向 js 傳值則須要控制器的 evaluateJavascript 方法。
WebView(
  // webview的url
  initialUrl: url ?? 'https://www.baidu.com/',
  // 監聽頁面url的變化,根據返回值決定跳轉仍是阻止
  navigationDelegate: (request) {
    if (request.url.startsWith('https://www.youtube.com/')) {
      print('blocking navigation to $request}');
      return NavigationDecision.prevent;
    }

    return NavigationDecision.navigate;
  },
  // flutter向js注入全局變量,而後js就能夠調用flutter的方法
  // 例子中js的window會多出一個 Print 對象,js調用Print.postMessage('我是js')時,在flutter中則會打印 js傳過來的值: 我是js
  javascriptChannels: {
    JavascriptChannel(
      name: 'Print',
      onMessageReceived: (JavascriptMessage msg) {
        print('js傳過來的值: ' + msg.message);
      }
    ),
  },
  // 是否容許運行js
  javascriptMode: JavascriptMode.unrestricted,
  // webview 建立後膚將控制器賦值給實例變量,方便控制
  onWebViewCreated: (webViewController) {
    // _controller.complete(webViewController);
    _webViewController = webViewController;
  },
  // 頁面加載完成
  onPageFinished: (String msg) {
    // print('加載完成');
  },
)
複製代碼
  1. 在後退時,默認使用的是 flutter 的後退方式,若是須要在 webview 內進行回退,則須要在外面包一層 WillPopScope來監聽頁面的返回,從而進行更改。
Future<bool> back() async {
  bool canBack = await _webViewController?.canGoBack();
  if (canBack) {
    _webViewController.goBack();
  } else {
    Navigator.of(context).pop();
  }

  return false;
}
複製代碼
  1. 使用控制器的 evaluateJavascript能夠經過 flutter 執行 js,從而獲得 js 返回的值或是向 js 中注入變量(好比用戶信息等),但這是有限制的。在安卓,執行後返回的值是 JSON 格式化後的字符串。而在 iOS 中,只有基本類型的字符串,數組類型的字符串能夠被返回,其餘非基本類型則不被支持而且該Future 會以 error 形式返回。

3. HTTP 請求庫:dio

安裝

dio: ^3.0.1
複製代碼

使用

dio 的使用方式跟前端平時使用的 axios 區別不是很大,因此我在這裏就只說一下我以前遇到的困難。github

  1. dio 的 interceptors 問題。其實這個主要仍是 dart 學習的很差,在函數或者方法之外,只能聲明變量,可是不能執行實例的方法,因此下述的代碼會報錯。
Dio dio = new Dio();
dio.interceptors.add(DioCacheManager(CacheConfig(baseUrl: baseUrl)).interceptor);
複製代碼

因此要封裝某一個類 A 的時候,得新建一個類 B,而後在 B 的某一個方法中執行 A 的方法,進行操做後再進行返回。代碼在這裏web

  1. 在進行 http 請求時,根據參數來選擇是否顯示 loading 框。看了文檔之後,發現 extra 參數在請求和響應中都存在,可是文檔中並無提示 extra 是怎麼傳入的。後來看了類型提示,發現 extra 參數是包含在請求參數的 options 中的。其實,沒有必要經過 extra 傳遞 loading 這個參數,能夠直接在請求的地方進行封裝。關於 loading 框的代碼在這裏json

  2. 處理響應數據,根據後端的錯誤碼進行相應處理。原本想在 interceptors 中對響應數據進行處理的,可是若是這麼處理以後,返回數據的類型提示就不正確了,因此最後仍是在拿到響應數據以後才進行處理的。redux

4. json 轉 dart 類:json_model

安裝

dependencies:
 json_annotation: ^2.0.0
dev_dependencies:
 json_model: ^0.0.2
 build_runner: ^1.0.0
 json_serializable: ^2.0.0
複製代碼

使用

  1. 項目根目錄下新建 jsons 文件夾
  2. 在該文件夾下新建 json 文件
  3. 執行 flutter packages pub run json_model

5. http 請求緩存:dio-http-cache

安裝

dependencies:
 dio_http_cache: ^0.2.0
複製代碼

dio-http-cache 的 0.2.0 版本與 json_model 庫依賴衝突,爲解決依賴衝突依賴衝突

json_model的依賴目前是
 json_annotation: ^2.2.0
 json_serializable: ^2.0.0

爲了兼容http_cache,須要升級這兩個依賴包的版本
 json_annotation: ^3.0.0
 json_serializable: ^3.0.0
複製代碼

使用

  1. 在dio中添加 dio-http-cache interceptor
dio.interceptors.add(DioCacheManager(CacheConfig(baseUrl: "http://www.google.com")).interceptor);
複製代碼
  1. 在請求options中添加
options: buildCacheOptions(
  Duration(days: 7),
  forceRefresh: true,
  options: Options(
    headers: headers,
    method: method,
    extra: {
      'needLoading': needLoading ?? true,
      ...(extra ?? {}),
    },
  ),
)
複製代碼

6. toast 庫:bot_toast

爲何 toast 還須要使用單獨的庫呢?由於在 flutter 中,要顯示 toast 的話,通常都須要使用到 BuildContext context,而使用這個庫的話,只須要用 BotToastInit 控件包裹一次,以後就能夠直接使用了;不然就須要創建一個全局變量的 context(不知道是否可行)或是每次都傳入 context。

flutter的initState 聲明週期中,能夠獲得 context,但沒法真正使用它,由於框架尚未徹底將其與 state 關聯。直到 initState() 方法執行完成,State 對象就被初始化而且 context 變爲可用。因此在 initState 方法中進行 http 請求時,不能直接顯示 toast。

// 第一幀 build 結束時觸發,此時context可用
void initState() {
  super.initState();
  WidgetsBinding.instance.addPostFrameCallback((callback){

  });
}
複製代碼

安裝

dependencies:
 bot_toast: ^2.1.0
複製代碼

使用

  1. 導入 BotToast 庫
import 'package:bot_toast/bot_toast.dart';
複製代碼
  1. 初始化 BotToast
// 1.使用BotToastInit直接包裹MaterialApp
BotToastInit(
  child: MaterialApp(
    title: 'BotToast Demo',
    // 2.註冊路由觀察者
    navigatorObservers: [BotToastNavigatorObserver()],
    home: XxxxPage(),
  )
);
複製代碼
  1. 使用 BotToast
BotToast.showText(text:"xxxx");  //彈出一個文本框;
複製代碼
BotToast.showSimpleNotification(title: "init"); //彈出簡單通知Toast
複製代碼
BotToast.showLoading(); //彈出一個加載動畫
複製代碼

7. 上拉加載下拉刷新:flutter_easyrefresh

安裝

dependencies:
 flutter_easyrefresh: ^2.0.4
複製代碼

使用

代碼在這裏

不得不說,這個庫真是至關的方便,比 web 端寫起來要簡單的多了。官方文檔寫的已經很詳細了,我就不寫了。

8. 輪播圖:flutter_swiper

安裝

dependencies:
 flutter_swiper: ^1.1.6
複製代碼

使用

代碼在這裏

這個庫也是很強大了,基本上經常使用的功能都有。

若是要實現 tab 與 swiper 聯動的話,

// swiper onIndexChanged
Swiper(
  itemCount: 2,
  itemBuilder: (context, index) {
    return Container(
      color: Color(0xFF82B1FF),
      child: Center(child: Text('$index',)),
    );
  },
  onIndexChanged: (index) {
    _tabController.index = index;
  },
  controller: _swiperController,
)

// tab onTap
TabBar(
  tabs: tabs,
  labelPadding: EdgeInsets.only(bottom: 12.0),
  indicatorSize: TabBarIndicatorSize.label,
  indicatorWeight: 3.0,
  onTap: (int index) {
    _swiperController.move(index);
  },
  controller: _tabController,
)
複製代碼

9. 狀態管理:Event Bus

flutter 的狀態管理庫仍是挺多的,好比官方推薦的 Provider,還有 redux,mobx,bloc,rxdart 等,主要是目前的項目還很小,須要狀態共享的地方很少,我就用 event bus 先湊合了。

安裝

dependencies:
 event_bus: 1.1.0
複製代碼

使用

  1. 建立一個實例
import 'package:event_bus/event_bus.dart';

EventBus eventBus = EventBus();
複製代碼
  1. 定義事件類
class PieceEvent {
  bool isBlack;
  PieceEvent({ this.isBlack = true });
}
複製代碼
  1. 監聽該事件
eventBus.on<PieceEvent>().listen((event) {
  setState(() {
    isBlack = event.isBlack;
  });
});
複製代碼
  1. 觸發該事件
eventBus.fire(PieceEvent(isBlack: isBlack));
複製代碼

10. 其餘

  1. [譯] Flutter 核心概念詳解: Widget、State、Context 及 InheritedWidget
  2. Stateful Widget Lifecycle
  3. material icon
  4. emoji

代碼地址: github.com/ma125120/fl…

相關文章
相關標籤/搜索