基於以前的新版本發佈version已經支持開始支持了Web開發者開發,那這個編程語言的前景已經不言而喻了,不只僅是一門跨雙端的編程語言,更是可能成爲將來的主流語言之一。當前這句話說的有點絕對,可是和React Native這一類語言不一樣的地方偶爾可能也是顯而易見的,基於的底層框架的修改,前者基於的是JS的一種擴展。因此接下來就是對這個編程語言的一種學習了。前端
另外本文應該會呈現4-5天的持續性更新,基於的後臺將是泓洋大神的wanandroid,有興趣的讀者均可以學習一下。java
Flutter中文網,安裝步驟及基礎使用等都已經在這份文檔裏了。android
材料清單:
1. 操做系統:OSX 10.15.3
2. Flutter版本:flutter_macos_v1.12.13+hotfix.7-stable
3. 軟件:Android Studio
複製代碼
我一頓猛如虎的操做下來基本是沒有問題的,不過Gtihub
上拉,確實有點慢,能夠直接下載穩定版玩兒。git
項目的源碼將集成在WanAndroid-Flutter中,由於項目是android官網推出的,因此直接講解。github
經過以上的這些基礎內容,咱們基本上就能夠開始初級的開發了。 見於對整個開發代碼的審閱,咱們將基於Flutter Inspector
對總體的代碼進行觀察。 macos
見於官方文檔中一樣建議咱們使用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已經作好的數據。json
|-- libs
|-- api (Api接口)
|-- common (公共類)
|-- fonts (字體類)
|-- model (Bean類)
|-- pages (UI頁面)
|-- util (工具類)
|-- widget (自定義組件)
複製代碼
由於頁面的邏輯基本一致,其實咱們只用分析單個頁面,就能徹底理解總體代碼的邏輯了。 這裏主講的是一個project
也就項目頁。設計模式
![]() |
![]() |
---|
拋出顯示效果,其實總體的框架就是一個TabBar
、RefreshIndicator
還有Card
的組合其實進入之後也能很清楚的發現。在界面上出現了一些叉叉的符號,那是由於個人刪減程序中並無加入字體庫。api
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的性能優化