前言
基於之前的新版本釋出version已經支援開始支援了Web開發者開發,那這個程式語言的前景已經不言而喻了,不僅僅是一門跨雙端的程式語言,更是可能成為未來的主流語言之一。當前這句話說的有點絕對,但是和React Native這一類語言不同的地方偶爾可能也是顯而易見的,基於的底層框架的修改,前者基於的是JS的一種擴充套件。所以接下來就是對這個程式語言的一種學習了。
另外本文應該會呈現4-5天的持續性更新,基於的後臺將是泓洋大神的wanandroid,有興趣的讀者都可以學習一下。
Flutter中文網,安裝步驟及基礎使用等都已經在這份文件裡了。
逃不過的安裝
材料清單:
1. 作業系統:OSX 10.15.3
2. Flutter版本:flutter_macos_v1.12.13+hotfix.7-stable
3. 軟體:Android Studio
複製程式碼
我一頓猛如虎的操作下來基本是沒有問題的,不過Gtihub
上拉,確實有點慢,可以直接下載穩定版玩兒。
專案的原始碼將整合在WanAndroid-Flutter中,因為專案是android官網推出的,所以直接講解。
使用
通過以上的這些基礎內容,我們基本上就可以開始初級的開發了。
見於對整個開發程式碼的審閱,我們將基於Flutter Inspector
對整體的程式碼進行觀察。
開發
- 網路部分
見於官方文件中同樣建議我們使用dio
進行網路請求,所以整體的網路請求及資料解析將依靠json_serializable
+dio
。
建立類似如下模版:
@JsonSerializable()
class User{
User(this.name, this.email);
String name;
String email;
//不同的類使用不同的mixin即可
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
複製程式碼
編碼完成以後,執行命令列flutter packages pub run build_runner build
,就會自動生成.g.dart
檔案就可以進行使用了。
因為沒有類似於Java
的反射機制,所以格式化的過程一般會比較麻煩,當然也可以去搜尋解析的框架。
另外在原始碼中,因為書寫方式是鑑於wanandroid
一個開放的專案,已經比較符合規範,所以可以選擇直接謄寫。
另外因為資料的原因,其實我還是直接建議呼叫這個demo已經做好的資料。
專案結構
|-- libs
|-- api (Api介面)
|-- common (公共類)
|-- fonts (字型類)
|-- model (Bean類)
|-- pages (UI頁面)
|-- util (工具類)
|-- widget (自定義元件)
複製程式碼
單個模組分析
因為頁面的邏輯基本一致,其實我們只用分析單個頁面,就能完全理解整體程式碼的邏輯了。
這裡主講的是一個project
也就專案頁。
丟擲顯示效果,其實整體的框架就是一個TabBar
、RefreshIndicator
還有Card
的組合其實進入以後也能很清楚的發現。在介面上出現了一些叉叉的符號,那是因為我的刪減程式中並沒有加入字型庫。
apkLink: ,
author: Mstian,
chapterId: 402,
chapterName: 跨平臺應用,
collect: false,
courseId: 13,
desc: 使用前端跨端框架開發一款安卓版本的玩安卓App,具體實現了登入註冊, 體系, 公眾號, 專案列表功能, 還有導航功能, 收藏文章專案功能等。 還使用了高德地圖api實現機主定位功能。,
envelopePic: https: //www.wanandroid.com/blogimgs/aeb17245-d43c-4ad3-ac35-aae45096aef8.png,
fresh: false,
id: 10726,
link: https://www.wanandroid.com/blog/show/2714,
niceDate: 2019-12-06 16:02,
origin: ,
projectLink: https://github.com/Mstian/wanAndroid,
publishTime: 1575619327000,
superChapterId: 294,
superChapterName: 開源專案主Tab,
tags: [Instance of 'ArticleTagModel'],
title: 前端框架uniapp版玩安卓客戶端,
type: 0,
userId: -1,
visible: 1,
zan: 0
複製程式碼
這份json
資料其實就是抓取來的資料之一,他所對應的就是Card
,也就是我們所看到的卡片,對應的就是ArticleItemPage.dart
。
而我們看到的列表的呈現、下拉重新整理、上拉載入也只是一個ListView
和RefreshIndicator
的結合使用,下面使用到原始碼中的一段進行驗證。
程式碼位於ArticleListPage.dart
中
listView = ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
itemCount: itemCount,
controller: getControllerForListView(),
itemBuilder: (context, index) {
if (index == 0 && null != widget.header) {
// 當資料為0,並且存在頭部時,就返回頭部
return widget.header;
} else if (index - (null == widget.header ? 0 : 1) >=
_listData.length) {
// 如果出現index大於資料長度,就出現載入更多
return _buildLoadMoreItem();
} else {
// 正常範圍狀態下,就構建Item
return _buildListViewItemLayout(
context, index - (null == widget.header ? 0 : 1));
}
});
var body = NotificationListener<ScrollNotification>(
onNotification: onScrollNotification,
child: RefreshIndicator(
child: listView,
color: GlobalConfig.colorPrimary,
onRefresh: handleRefresh,
),
);
複製程式碼
這裡其實也就是我所說的那一系列程式碼的核心了,中間還有一些分頁的功能以及快取的工作,可以詳見ProjectPage.dart
中的下述程式碼
因為這部分程式碼和
ArticleListPage.dart
的耦合,所以放在一起講。
Widget _buildSinglePage(ProjectClassifyItemModel bean) {
return ArticleListPage(
keepAlive: _keepAlive(),
request: (page) {
return CommonService().getProjectListData((bean.url == null)
? ("${Api.PROJECT_LIST}$page/json?cid=${bean.id}")
: ("${bean.url}$page/json"));
},
);
}
bool _keepAlive() {
if (_cachedPageNum < _maxCachePageNums) {
_cachedPageNum++;
return true;
} else {
return false;
}
}
複製程式碼
在這個dart
檔案中,存在一個網路請求和快取數,快取就是通過上述的一個_keepAlive()
的函式進行操作的。
網路請求
網路請求部分其實才是整個專案的重點。
筆主將原有的模式,進行了一定的修改,從設計模式上來講就是單例模式中的惡漢式,從java
以及我個人的角度來講,因為網路請求是一個一定會被使用到的變數,通過餓漢式的建立方法,其實也是對效能的一種優化。
先呼叫一份dio
的使用方法。
在這個專案中,我們頻繁的會看到類似如下程式碼
CommonService().getProjectListData((bean.url == null)
? ("${Api.PROJECT_LIST}$page/json?cid=${bean.id}")
: ("${bean.url}$page/json"))
複製程式碼
這其實是寫程式碼的人對這個網路請求的一個封裝。
而為了通過拿到真實資料我們的一般操作模版如下程式碼所示
dio.get(Api.PROJECT_CLASSIFY, options: _getOptions()).then((response) {
callback(ProjectClassifyModel.fromJson(response.data));
});
複製程式碼
其實原理很簡單,我們還記得自己創造的bean
嗎?通過呼叫他的fromJson()
函式,我們就能得到了相對的資料實體了。
讓我們在看下Dio
中的Reponse
。
{
/// Response body. may have been transformed, please refer to [ResponseType].
T data;
/// Response headers.
Headers headers;
/// The corresponding request info.
Options request;
/// Http status code.
int statusCode;
/// Whether redirect
bool isRedirect;
/// redirect info
List<RedirectInfo> redirects ;
/// Returns the final real request uri (maybe redirect).
Uri realUri;
/// Custom field that you can retrieve it later in `then`.
Map<String, dynamic> extra;
}
複製程式碼
這個類中的變數很多,不過因為data中儲存的是伺服器傳回來的資料,所以我們也就知道了為什麼一般呼叫是data
這個變數了。
另外還有一個點就是我們經常在網路請求中看到的兩個關鍵詞async
和await
,這兩個變數就是為了讓我們進行非同步處理,知道ANR機制的讀者們,想來也就清楚了非同步處理的重要性了。
另外這個專案因為是類似於元件化的開發,不過最近幾年元件化開發興起,確實有著它難以想象的好處,不論是複用機制,還是節省開發成本,他都帶來了難以想象的好處,所以這個開發模式還是很建議學習的。
以上就是我的學習成果,如果有什麼我沒有思考到的地方或是文章記憶體在錯誤,歡迎與我分享。
相關文章推薦: Flutter的效能優化