一周时间编写你的第二个 Flutter APP

前言

Flutter 从发布之日起我就对其心心念念了好久。
奈何这段时间实在是太忙了,加之自己拖延症时不时发作下,一直都抽不出时间来学习这个跨平台框架。

一转眼 Flutter 1.2 都已经发布了,这下实在是坐不住了。特地花了一周的时间来做了 一文 这个 APP 。以此来简单了解下这款全新跨平台框架的魅力。

image

第一个 APP

回到标题,既然是编写第二个 Flutter APP,那就要求各位观众老爷自己对照着官方的 First Flutter APP 撸一遍。(中文链接:https://flutterchina.club/get-started/codelab/)

万事开头难,这部分包含了 dart 语言特性的学习,和 Flutter 框架一些特性的体验。

如果你也是像我一样只是花两个小时简单看了下 dart 语言的新特性就直接来撸第一个 APP。写的时候可能会感觉总是在云里雾里,很多地方都不明白。

别担心,这是正常现象,对我们这种只想初步体验的用户来说,没有系统的学习,这种情况才是正常现象。

保持开放的心态,多学多看。碰到不懂的,多查,碰到不知道怎么写的,多看官方的源码实现,等代码量上去了,自然就熟练了。

第二个 APP

照着官方示例完成了自己了的第一个 APP 编写,是不是很有成就感?激动之余,似乎感觉少了点什么。

没错,毕竟只是照着官方的示例敲了一遍,说是 APP 也略简陋了。是不是迫不及待的想做点什么来巩固下自己的学习呢。

这次就跟着我一起从项目的立项开始你的第二个 APP 吧。

一文

由于项目一周的时间限制,本次就要求项目尽可能的简单,页面尽可能的少。且,要尽可能的完成多的功能点,于是 一文 就诞生了。

一文 是基于每日一文 API 开发的一款全新的 Flutter APP。

下载

https://github.com/chengww5217/one_article/releases

截图

image
image
image
image

Highlights

  • 这个项目足够简单
    • 只有 splash、home、starred list 三个界面
  • 这个项目功能点足够多
    • splah 页面创建,去除启动白屏
    • 联网、Json 解析、文章展示
    • 数据库保存文章
    • 主题切换,字体调整,配置本地保存(SP)
    • 国际化
    • ···
  • 这个项目还是有用的
    • 和一般纯练手 Demo 不同,每日一文是我每天都会看的

开始项目

注意:在源代码中,一个页面可能包含多个功能实现,在实际做的时候,请依据 APP 预览一项一项进行实现。

源代码并不是标准答案,有问题欢迎提交 PR 进行贡献。

API

API 来源:https://github.com/jokermonn/-Api/blob/master/OneArticle.md

分析 API 进行联网实现,主要要求实现联网获取文章,获取后进行 Json 解析到 bean,然后进行简单的错误 handle。

参考文章:

Splash Page

按照原生 APP 开发的套路,用于初始化以及展示广告的 Splash 是必不可少的。

第一个页面,主要要求掌握页面编写的常规套路以及 StatefulWidget 的生命周期等。

比如 class SplashPage 的写法:

class SplashPage extends StatefulWidget {
  SplashPage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  State<StatefulWidget> createState() {
    return _SplashPageState();
  }
}

然后就是 class _SplashPageState 的编写。

布局就是一张图片:

import 'package:flutter/material.dart';

class SplashPage extends StatefulWidget {
  SplashPage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  State<StatefulWidget> createState() {
    return _SplashPageState();
  }
}

class _SplashPageState extends State<SplashPage> {
  
  @override
  void initState() {
    // TODO: do something to init
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Builder(builder: (context) {
      return Container(
        child: Image(image: AssetImage('assets/images/splash.png'), fit: BoxFit.fill,),
      );
    });
  }
}

生命周期如下:

image

图片转载自https://segmentfault.com/a/1190000015211309

具体 Splash 页面讲解参考我的博客:Flutter 开发 Android & IOS 启动页 splash page

Home Page

主页面主要是对文章进行展示以及相关设置项。

image

点击左上角可以弹出相关配置弹窗。

考虑到布局的复杂度,这里可以将底部弹窗抽离出单独写进一个 .dart 文件。

从这部分就涉及到各个控件的使用和状态设置,点击事件等内容。

这部分基本就是程序的核心内容了。


完成了该部分之后就是对程序进行优化,添加数据库来缓存数据,日期判断切换,文章收藏等。

这个部分是耗时最长的,也是从磕磕碰碰到逐渐熟练的过程。

杂项

最后就是国际化,添加资源和打包等一些杂项了,具体参见

https://flutter.dev/docs/development/accessibility-and-localization/internationalization

https://flutter.dev/docs/deployment/android

结语

从刚开始看 dart 语法,到这个项目开发完成。断断续续一共持续了三周的时间。每天抽出一到两个小时,合计一共是 56 小时左右。减去画 APP 图标,启动页面图片的两个小时,勉强算得上八小时工作制的一周。

这一周的使用过程中,Flutter 有些特性让人感觉相见恨晚:语法特性(类型动态检查,支持 .? ?? 操作符)、简单方便完备的 UI 方案、Hot Reload等。但是诸如复杂冗长的 view tree、资源的硬编码、糟糕的 UI 控件 API 等又让人头痛不已。

在初步使用 Flutter 之后,我发觉似乎 Flutter 短时间内并不能让我不学习原生开发就直接使用 Flutter 解决移动客户端开发。

在不断的使(zhe)用(teng)过程中,发现碰到好多问题还是需要你必须用原生开发的知识去解决相应的问题。 比如项目里面获取已收藏文章,是这样从数据库里面获取文件的:

Future<List<ArticleBean>> getStarred() async {
    List<ArticleBean> articles = List();
    Database db = await getDB();
    List<Map<String, dynamic>> maps =
    await db.query(name, columns: [columnId, columnStarred, columnDate, columnData], where: "$columnStarred = ?", whereArgs: [true]);
    if (maps.length > 0) {
      for (Map<String, dynamic> map in maps) {
        ArticleBean article = ArticleBean.fromJson(map);
        articles.add(article);
      }
    }
    return articles;
  }

请看核心查询代码

await db.query(name, columns: [columnId, columnStarred, columnDate, columnData], where: "$columnStarred = ?", whereArgs: [true]);

这里就是获取所有 starred 为 true 的列。

但是实际运行的时候,发现在 Android 设备上面总是获取不到。

Android 数据库使用的是 Sqlite,不能存储 bool(boolean)。相反,布尔值被存储为整数 0(false)和 1(true)。

故上述代码要改成下面的代码才生效。

await db.query(name, columns: [columnId, columnStarred, columnDate, columnData], where: "$columnStarred > ?", whereArgs: [0]);

这只是一个很小的简单例子,但是也说明了在 Flutter 上面并不能总是帮你解决原生的一些坑(这其实取决于各个框架的开发者为你做了多少兼容处理)。


本文到这里就要结束了,不怎么涉及具体代码,只是一周时间的 Flutter 简单上手。如果大家对项目有兴趣,欢迎大家 star、fork 以及提交 PR,谢谢大家。

项目地址:https://github.com/chengww5217/one_article

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

推荐阅读更多精彩内容