手撕Flutter开发

前言

基于之前的新版本发布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也就项目页。

抛出显示效果,其实整体的框架就是一个TabBarRefreshIndicator还有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

而我们看到的列表的呈现、下拉刷新、上拉加载也只是一个ListViewRefreshIndicator的结合使用,下面使用到源码中的一段进行验证。
代码位于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这个变量了。

另外还有一个点就是我们经常在网络请求中看到的两个关键词asyncawait,这两个变量就是为了让我们进行异步处理,知道ANR机制的读者们,想来也就清楚了异步处理的重要性了。

另外这个项目因为是类似于组件化的开发,不过最近几年组件化开发兴起,确实有着它难以想象的好处,不论是复用机制,还是节省开发成本,他都带来了难以想象的好处,所以这个开发模式还是很建议学习的。

以上就是我的学习成果,如果有什么我没有思考到的地方或是文章内存在错误,欢迎与我分享。


相关文章推荐:
Flutter的性能优化

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343