開源一個Flutter版WanAndroid客戶端

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包起來

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章