手撕Flutter开发

前言

基于以前的新版本发布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也就项目页。设计模式

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

而咱们看到的列表的呈现、下拉刷新、上拉加载也只是一个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的性能优化

相关文章
相关标签/搜索