一個高顏值Flutter版WanAndroid客戶端

瀟風寒月發表於2020-04-11

1. 前言

專案地址: https://github.com/xfhy/WanAndroid-Flutter

前段時間抽了點業餘時間學了點Flutter入門,打算寫個簡單專案練練手.說實話,只有真正動手寫東西才能真正切身感受到Flutter的魅力,剛開始學的時候寫佈局特別難受,各種巢狀,很煩. 後面多寫一點兒之後感覺也還是勉強可以接受,各種Widget操作起來也還是容易.

Flutter目前我認為是最合理的跨平臺方案,只需要native提供畫布,Flutter直接自己在上面畫Widget,就單憑這一點就和RN截然不同.RN還需要JS和Java進行中轉,多了一層,肯定會慢很多,而且還不能自己畫.

再來說說開發和釋出,支援JIT和AOT.平時開發使用JIT,可以快速熱載入,及時將程式碼變動傳遞給flutter app,這其實可以大大提升開發效率.及時檢視UI和邏輯是否正確,不像原生開發還需要重新編譯,花費很多時間.然後Flutter在釋出(release包)的時候,採用AOT,執行時直接指向Native(arm)程式碼,高效.

可能有時候Flutter需要和native通訊,比如使用相機之類的,這時會使用到channel技術,但是這個是C++層次的,效能好.

所以,瞭解一下Flutter.

2. 下載試玩

掃描二維碼下載

3. 技術點

  • 封裝 上拉載入,下拉重新整理
  • dio進行網路請求,統一封裝get,post
  • 封裝banner
  • Future
  • 路由,跳轉介面
  • 事件匯流排 event_bus
  • toast
  • SharedPreference
  • ....

4. 專案截圖

image1 image2 image3 image4 image6 image6

5. 遇到的問題

5.1 引入第三方庫

  1. 首先去官網package搜尋.
  2. 找到相應外掛,點進詳情,切換到Installing tab,然後在pubspec.yaml中引入該外掛.
  3. 在本專案控制檯,輸入flutter pub get. 即引入三方庫完成.

5.2 loading

當頁面正在loading時,需要一個Widget來佔位,不然Widget為空要報錯.

5.3 執行在iOS上

  1. 首先得安裝Xcode(7.8G)
  2. 然後安裝 cocoapods sudo gem install cocoapods
  3. 然後在ios工程下,執行pod install,引入那些依賴
  4. 然後用AS開啟ios專案裡面的Info.plist,點選右上角的用Xcode開啟.
  5. 編輯Podfile,將頂部的platform :ios, '9.0' 註釋放開
  6. 執行到模擬器上.

5.4 如何快速解析json

Flutter不支援執行時反射,所以沒有像Gson這樣自動解析JSON的庫來降低解析成本.在Flutter中解析JSON需要完全手動進行操作,麻煩.

可以在AS上裝FlutterJsonBeanFactory這個外掛,然後右鍵New->JsonToDartBeanAction,輸入檔名和json資料.即可自動生成bean物件,和它所對應的解析程式碼.

原理是它生成了一個JsonConvert,然後這裡面可以根據執行時type去選擇應該解析哪一個類物件. 然後bean類在宣告的時候是混入了JsonConvert的,可以直接使用JsonConvert裡面的方法,完美.

5.5 Flutter ScrollView (滾動檢視)

ScrollView是一個帶有滾動的檢視元件,它本身由三部分組成

  • Scrollable - 它監聽各種使用者手勢並實現滾動的互動設計。
  • Viewport - 它通過在滾動檢視內僅顯示一部分小部件來實現滾動的視覺化設計。
  • Slider - 它們是可以組合以建立各種滾動效果的小部件,如列表,網格和擴充套件標題。

Scroll是一個抽象類,通常使用CustomScrollView

CustomScrollView(
    shrinkWrap: true,
    // 內容
    slivers: <Widget>[
        new SliverPadding(
            padding: const EdgeInsets.all(20.0),
            sliver: new SliverList(
                delegate: new SliverChildListDelegate(
                    <Widget>[
                        const Text('A'),
                        const Text('B'),
                        const Text('C'),
                        const Text('D'),
                    ],
                ),
            ),
        ),
    ],
)
複製程式碼

5.6 處理Text超出問題

可以放Row或Column中,用Expanded包起來,然後用maxLines控制行數,用overflow: TextOverflow.ellipsis,控制超出部分的展示.

5.7 讓一個ListView支援下拉重新整理

非常簡單, 使用官方自帶的RefreshIndicator即可,將listview放child,然後實現一個_pullToRefresh下拉重新整理時呼叫的方法(做下拉重新整理的邏輯).

RefreshIndicator(
      child: listView,
      onRefresh: _pullToRefresh,
    );

Future<void> _pullToRefresh() {
    loadData();
    //這裡Feature不能返回 null
    return Future(() => LogUtil.d("lalala"));
  }
複製程式碼

5.8 獲取螢幕寬度,高度

MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height
複製程式碼

5.9 封裝通用標題欄

標題欄,每個介面都需要,所以封裝一個,取需.

///get通用狀態列
static AppBar getCommonAppBar(BuildContext context, String title, {double fontSize, List<Widget> actions}) {
if (title == null) {
  title = "";
}
return AppBar(
  leading: IconButton(
    icon: Icon(
      Icons.arrow_back,
      color: Colors.white,
    ),
    //點選返回
    onPressed: () {
      if (context != null) {
        Navigator.pop(context);
      }
    },
  ),
  title: Text(
    title,
    style: TextStyle(
      color: Colors.white,
      fontSize: fontSize == null ? 18.0 : fontSize,
    ),
  ),
  //標題欄居中
  centerTitle: true,
  //右邊的action 按鈕
  actions: actions == null ? <Widget>[] : actions,
);
}
複製程式碼

5.10 格式化String

dart中格式化String,需要引入三方庫sprintf,使用方式如下:

sprintf("lg/collect/%s/json", [15615]);
複製程式碼

5.11 獲取Android/iOS本地目錄

需要引入三方庫path_provider,用於查詢檔案系統上的常用位置,支援Android和iOS.免得去寫一原生程式碼,這個三方庫幫我們封裝好了.

Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;

Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
複製程式碼

5.12 展示一個Dialog

以下方法是dart的material包下面的方法.

//展示對話方塊
showDialog(
        context: context,
        barrierDismissible: false,
        builder: (_) {
          return SpinKitFadingCircle(
            color: AppColors.colorPrimary,
          );
        });

//取消對話方塊
Navigator.of(context).pop();
複製程式碼

5.13 間距的簡單方式

可以用Padding和margin來實現.其實還有一種方式,可以在Column和Row中快速增加一段間距,利用SizedBox,類似Android中的Space

SizedBox(width: 10.0),
複製程式碼

5.14 收起軟鍵盤

有時候需要在點選某些按鈕時收起軟鍵盤

FocusScope.of(context).requestFocus(FocusNode());
複製程式碼

5.15 讓ListView的item點選時有水波紋效果

用InkWell把Item包起來

相關文章