1. 前言
項(xiàng)目地址: https://github.com/xfhy/WanAndroid-Flutter
前段時(shí)間抽了點(diǎn)業(yè)余時(shí)間學(xué)了點(diǎn)Flutter入門,打算寫個(gè)簡(jiǎn)單項(xiàng)目練練手.說(shuō)實(shí)話,只有真正動(dòng)手寫東西才能真正切身感受到Flutter的魅力,剛開始學(xué)的時(shí)候?qū)懖季痔貏e難受,各種嵌套,很煩. 后面多寫一點(diǎn)兒之后感覺也還是勉強(qiáng)可以接受,各種Widget操作起來(lái)也還是容易.
Flutter目前我認(rèn)為是最合理的跨平臺(tái)方案,只需要native提供畫布,Flutter直接自己在上面畫Widget,就單憑這一點(diǎn)就和RN截然不同.RN還需要JS和Java進(jìn)行中轉(zhuǎn),多了一層,肯定會(huì)慢很多,而且還不能自己畫.
再來(lái)說(shuō)說(shuō)開發(fā)和發(fā)布,支持JIT和AOT.平時(shí)開發(fā)使用JIT,可以快速熱加載,及時(shí)將代碼變動(dòng)傳遞給flutter app,這其實(shí)可以大大提升開發(fā)效率.及時(shí)查看UI和邏輯是否正確,不像原生開發(fā)還需要重新編譯,花費(fèi)很多時(shí)間.然后Flutter在發(fā)布(release包)的時(shí)候,采用AOT,運(yùn)行時(shí)直接指向Native(arm)代碼,高效.
可能有時(shí)候Flutter需要和native通信,比如使用相機(jī)之類的,這時(shí)會(huì)使用到channel技術(shù),但是這個(gè)是C++層次的,性能好.
所以,了解一下Flutter.
2. 下載試玩
掃描二維碼下載
3. 技術(shù)點(diǎn)
- 封裝 上拉加載,下拉刷新
- dio進(jìn)行網(wǎng)絡(luò)請(qǐng)求,統(tǒng)一封裝get,post
- 封裝banner
- Future
- 路由,跳轉(zhuǎn)界面
- 事件總線 event_bus
- toast
- SharedPreference
- ....
4. 項(xiàng)目截圖
5. 遇到的問題
5.1 引入第三方庫(kù)
- 首先去官網(wǎng)package搜索.
- 找到相應(yīng)插件,點(diǎn)進(jìn)詳情,切換到Installing tab,然后在pubspec.yaml中引入該插件.
- 在本項(xiàng)目控制臺(tái),輸入flutter pub get. 即引入三方庫(kù)完成.
5.2 loading
當(dāng)頁(yè)面正在loading時(shí),需要一個(gè)Widget來(lái)占位,不然Widget為空要報(bào)錯(cuò).
5.3 運(yùn)行在iOS上
- 首先得安裝Xcode(7.8G)
- 然后安裝 cocoapods
sudo gem install cocoapods
- 然后在ios工程下,執(zhí)行
pod install
,引入那些依賴 - 然后用AS打開ios項(xiàng)目里面的Info.plist,點(diǎn)擊右上角的用Xcode打開.
- 編輯Podfile,將頂部的
platform :ios, '9.0'
注釋放開 - 運(yùn)行到模擬器上.
5.4 如何快速解析json
Flutter不支持運(yùn)行時(shí)反射,所以沒有像Gson這樣自動(dòng)解析JSON的庫(kù)來(lái)降低解析成本.在Flutter中解析JSON需要完全手動(dòng)進(jìn)行操作,麻煩.
可以在AS上裝FlutterJsonBeanFactory這個(gè)插件,然后右鍵New->JsonToDartBeanAction,輸入文件名和json數(shù)據(jù).即可自動(dòng)生成bean對(duì)象,和它所對(duì)應(yīng)的解析代碼.
原理是它生成了一個(gè)JsonConvert,然后這里面可以根據(jù)運(yùn)行時(shí)type去選擇應(yīng)該解析哪一個(gè)類對(duì)象.
然后bean類在聲明的時(shí)候是混入了JsonConvert的,可以直接使用JsonConvert里面的方法,完美.
5.5 Flutter ScrollView (滾動(dòng)視圖)
ScrollView是一個(gè)帶有滾動(dòng)的視圖組件,它本身由三部分組成
- Scrollable - 它監(jiān)聽各種用戶手勢(shì)并實(shí)現(xiàn)滾動(dòng)的交互設(shè)計(jì)陕习。
- Viewport - 它通過在滾動(dòng)視圖內(nèi)僅顯示一部分小部件來(lái)實(shí)現(xiàn)滾動(dòng)的可視化設(shè)計(jì)创千。
- Slider - 它們是可以組合以創(chuàng)建各種滾動(dòng)效果的小部件潮峦,如列表,網(wǎng)格和擴(kuò)展標(biāo)題荆姆。
Scroll是一個(gè)抽象類,通常使用CustomScrollView
CustomScrollView(
shrinkWrap: true,
// 內(nèi)容
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包起來(lái),然后用maxLines控制行數(shù),用overflow: TextOverflow.ellipsis,
控制超出部分的展示.
5.7 讓一個(gè)ListView支持下拉刷新
非常簡(jiǎn)單,
使用官方自帶的RefreshIndicator即可,將listview放child,然后實(shí)現(xiàn)一個(gè)_pullToRefresh下拉刷新時(shí)調(diào)用的方法(做下拉刷新的邏輯).
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 封裝通用標(biāo)題欄
標(biāo)題欄,每個(gè)界面都需要,所以封裝一個(gè),取需.
///get通用狀態(tài)欄
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,
),
//點(diǎn)擊返回
onPressed: () {
if (context != null) {
Navigator.pop(context);
}
},
),
title: Text(
title,
style: TextStyle(
color: Colors.white,
fontSize: fontSize == null ? 18.0 : fontSize,
),
),
//標(biāo)題欄居中
centerTitle: true,
//右邊的action 按鈕
actions: actions == null ? <Widget>[] : actions,
);
}
5.10 格式化String
dart中格式化String,需要引入三方庫(kù)sprintf
,使用方式如下:
sprintf("lg/collect/%s/json", [15615]);
5.11 獲取Android/iOS本地目錄
需要引入三方庫(kù)path_provider
,用于查找文件系統(tǒng)上的常用位置,支持Android和iOS.免得去寫一原生代碼,這個(gè)三方庫(kù)幫我們封裝好了.
Directory tempDir = await getTemporaryDirectory();
String tempPath = tempDir.path;
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
5.12 展示一個(gè)Dialog
以下方法是dart的material包下面的方法.
//展示對(duì)話框
showDialog(
context: context,
barrierDismissible: false,
builder: (_) {
return SpinKitFadingCircle(
color: AppColors.colorPrimary,
);
});
//取消對(duì)話框
Navigator.of(context).pop();
5.13 間距的簡(jiǎn)單方式
可以用Padding和margin來(lái)實(shí)現(xiàn).其實(shí)還有一種方式,可以在Column和Row中快速增加一段間距,利用SizedBox,類似Android中的Space
SizedBox(width: 10.0),
5.14 收起軟鍵盤
有時(shí)候需要在點(diǎn)擊某些按鈕時(shí)收起軟鍵盤
FocusScope.of(context).requestFocus(FocusNode());
5.15 讓ListView的item點(diǎn)擊時(shí)有水波紋效果
用InkWell把Item包起來(lái)